bzoj 1041: [HAOI2008]圆上的整点

来源:互联网 发布:网络诋毁企业 编辑:程序博客网 时间:2024/05/16 05:05

1041: [HAOI2008]圆上的整点

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4140  Solved: 1875
[Submit][Status][Discuss]

Description

  求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。

Input

  只有一个正整数n,n<=2000 000 000

Output

  整点个数

Sample Input

4

Sample Output

4


因为n特别大,所以枚举肯定超时

那怎么办呢?

圆的方程式:X²+Y² = R²

那么可得Y² = R²-X² = (R+X)*(R-X)

令d = Gcd(R+X, R-X)

那么有Y² = d²*(R+X)/d*(R-X)/d

再设A = (R+X)/d,B = (R-X)/d

那么有Y² = d²*A*B,所以要想Y是整数,A*B一定要是一个完全平方数

又因为Gcd(A, B)==1,所以A和B一定都是完全平方数

到这就好办了

A = a², B = b²

那么有(R+X)/d, = (R-X)/d

a²+b² = 2*R/d

这说明d一定是2*R的一个约数,只要枚举2*R的约数d,

对于2*R%d==0,再枚举对应的a和b是多少,之后判断一波A和B是否互质即可,只要互质ans++

枚举约数都是更号的复杂度,所以不用担心超时

因为4个象限+4个坐标轴上的点

所以最后答案×4再+4


#include<stdio.h>#include<math.h>#define LL long longLL Gcd(LL a, LL b){if(a%b==0)return b;return Gcd(b, a%b);}int main(void){LL R, d, i, j, ans;while(scanf("%lld", &R)!=EOF){ans = 0;for(d=1;d*d<=2*R;d++){if((2*R)%d==0){for(i=1;i*i<=R/d;i++){j = sqrt(2.0*R/d-i*i);if(i*i+j*j==2*R/d && Gcd(i*i, j*j)==1 && i!=j)ans++;}if(d*d==2*R)continue;for(i=1;i*i<=d/2;i++){j = sqrt(1.0*d-i*i);if(i*i+j*j==d && Gcd(i*i, j*j)==1 && i!=j)ans++;}}}printf("%lld\n", ans*4+4);}return 0;}




原创粉丝点击