Description
明明觉得hash是个好算法,代码短、效率高。某天,他碰到了一个求正方形个数的问题,于是很淡定地枚举对角线然后用hash判存在,妥妥的搞定,但是提交后却wa了几个点。仔细观察其hash函数为: h=x*y+x+y 。为了让明明知道这个函数存在什么问题,对于给出一个h值,请你来告诉他有多少对(x,y)满足上述式子(max(x,y)<=h;h,x,y都为非负整数)。
Input
多组测试数据,第一行为测试点的个数T,接下来每一行一个整数h,意义如上。
Output
一共T行,每行一个整数,分别表示有多少组(x,y)满足要其对应的h值。
分析
第一眼看起来什么想法都没有
然后大神告诉我们——————
求一个数有多少个因数,可以先做质因数分解,然后统计每个质因子的个数,答案就出来了:
ans=ans*(fill[i]+1);(fill[i]为分解后第i个质因子的个数)
题目上的h=x*y+x+y可以变换成 h+1=(x+1)*(y+1)
令 s=h+1,a=x+1,b=y+1;于是题目就变成了:对于式子 s=a*b 有多少组(a,b)满足要求。
可以猥琐一下:我们只用预处理出10000以内的素数,分解质因数s的过程中,可能最后会剩下一个很大的质因数,超过了预处理出的素数上限。
这时只需要特判一下分解完后,s是否等于1,不是的话将答案*2就行了。
代码
var
i,j,k:longint;
flag:boolean;
h,n:longint;
ans:longint;
f:array[0..10000] of longint;
a:array[0..10100] of longint;
b:array[0..10100] of longint;
begin
for i:=2 to trunc(sqrt(10000)) do
if a[i]=0
then
for j:=2 to 10000 div i do
a[i*j]:=1;
a[1]:=1;
for i:=1 to 10000 do
if a[i]=0
then
begin
b[0]:=b[0]+1;
b[b[0]]:=i;
end;
readln(n);
for j:=1 to n do
begin
readln(h);
fillchar(f,sizeof(f),0);
h:=h+1;
flag:=true;
repeat
flag:=true;
for i:=1 to b[0] do
if h mod b[i]=0 then
begin
flag:=false;
inc(f[b[i]]);
h:=h div b[i];
end;
until flag;
ans:=1;
if h<>1 then ans:=2;
for i:=1 to b[0] do
if f[b[i]]<>0 then ans:=ans*(f[b[i]]+1);
writeln(ans);
end;
end.