Hash函数 纪中3094 数学

来源:互联网 发布:js如何设置div的高 编辑:程序博客网 时间:2024/05/24 07:03

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.
1 0
原创粉丝点击