bzoj1041: [HAOI2008]圆上的整点

来源:互联网 发布:考试失败 知乎 编辑:程序博客网 时间:2024/05/21 22:38

传送门
话说O(n)的做法大家都会吧。
接下来是神(gui)奇(chu)的变形
假设点在第一象限,坐标为(X,Y)
则R^2=X^2+Y^2
Y^2=R^2-X^2=(R+X)(R-X)
Y=sqrt((R+X)(R-X))
设gcd(R-X,R+X)=D,A=(R-X)/D,B=(R+X)/D
则Y=sqrt(D^2*A*B)=D*sqrt(A*B)
因为A,B互质(显然是的
所以A,B均为完全平方数。
设A=a^2,B=b^2
则有(R-X)/D=A=a^2,(R+X)/D=B=b^2
两式相加,得2R/D=a^2+b^2
所以D为2R的约数
那么我们可以先枚举D,在枚举a,通过2R/D=a^2+b^2计算出b
然后得到A,B,计算出X,判断其合法性。
得到答案仅为第一象限,因此要*4(四个象限)+4(x轴y轴)
这样就可以pass了。

var  r,d,u,v:int64;  i,ans,j:longint;function gcd(x,y:int64):int64;  begin if (y=0) then exit(x) else exit(gcd(y,x mod y)); end;begin  read(r); ans:=0;  for i:=1 to trunc(sqrt(2*r)) do    if (2*r mod i=0) then begin      d:=i;      for j:=1 to trunc(sqrt(2*r div d)) do begin        u:=j;        v:=trunc(sqrt(2*r div d-u*u));        if (u*u+v*v<>2*r div d) or (gcd(u,v)<>1) or (v<=u) then continue;        inc(ans);      end;      if (d*d<>2*r) and (d<>1) then begin        d:=2*r div i;        for j:=1 to trunc(sqrt(2*r div d)) do begin          u:=j;          v:=trunc(sqrt(2*r div d-u*u));          if (u*u+v*v<>2*r div d) or (gcd(u,v)<>1) or (v<=u) then continue;          inc(ans);        end;      end;    end;  write(ans*4+4);end.
0 0
原创粉丝点击