1041: [HAOI2008]圆上的整点
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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²
那么有a² = (R+X)/d,b² = (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 long
LL 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;
}
本文介绍了解决HAOI2008竞赛中圆上整点计数问题的方法。通过数学推导,利用圆的方程和约数特性,设计了一种高效算法,在大输入范围内快速找出圆周上所有整数坐标的点。
859

被折叠的 条评论
为什么被折叠?



