UOJ Logo zhouzixuan的博客

博客

bzoj 1041: [HAOI2008]圆上的整点

2015-05-24 19:49:22 By zhouzixuan
【题目大意】:
    求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
【题目解法】:
    其实这是一道陈题了,但是感觉方法很赞,于是写一下加深印象
    首先,我们把式子变一下形:x^2=(r-y)(r+y)
    然后我们设d=gcd(r-y,r+y),那么x^2=d*d*(r-y)/d*(r+y)/d
    然后我们设A=(r-y)/d  B=(r+y)/d 并且(A,B)=1(显然)
    那么原式可化为x^2=d^2*A*B,由于x^2 d^2都是完全平方数,并且(A,B)=1,所以A,B的乘积不可能为完全平方数,所以A B是完全平方数
    然后设A=a^2  B=b^2
    那么A+B=a^2+b^2=(r-y)/d+(r+y)/d=2*r/d
    所以d为2*r的约数,那么我们枚举所有2r的约数D
    所以有a^2+b^2=D
    然后一般的设a<b(因为a>b与a<b算出的答案是一样的)
    所以2*a^2<D 那么a^2<D/2,然后枚举sqrt(D/2)内所有的数a,然后判断a^2+b^2=D 且 (a*a,b*b)=1 且 a!=b,那么ans++
var
  ans:longint; n:int64;
procedure init;
begin
  readln(n); ans:=0;
end;
function gcd(x,y:longint):longint;
begin
  if y=0 then exit(x) else exit(gcd(y,x mod y));
end;
procedure main;
var
  i,j,a,d,limit:longint; b,k:int64;
begin
  k:=int64(trunc(sqrt(2*n)));
  limit:=k;
  for d:=1 to limit do
  begin
    if (2*n) mod d<>0 then continue;
    for a:=1 to trunc(sqrt(2*n/(2*d))) do
    begin
      b:=2*n div d-a*a;
      if sqrt(b)<>trunc(sqrt(b)) then continue;
      b:=trunc(sqrt(b));
      if (a=b) or (gcd(a,b)<>1) then continue;
      inc(ans);
    end;
    if 2*n div d=d then continue;
    for a:=1 to trunc(sqrt(d/2)) do
    begin
      b:=d-a*a; if b<0 then continue;
      if sqrt(b)<>trunc(sqrt(b)) then continue;
      b:=trunc(sqrt(b));
      if (a=b) or (gcd(a,b)<>1) then continue;
      inc(ans);
    end;
  end;
  writeln(ans*4+4);
end;
begin
  init;
  main;
end.

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。