Description
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
Input
r
Output
整点个数
Sample Input
4
Sample Output
4
HINT
n<=2000 000 000
Source
不要看见圆就以为是几何QwQ
这题其实TMD是数论啊(╯‵□′)╯︵┻━┻
推公式
x2+y2=r2 所以 y2=r2−x2=(r+x)(r−x)
可以发现 r+x 和 r−x 必定存在一个最大公约数为d.
那么 y2=d2r+xdr−xd
设后面那两个分式分别为A,B
那么一定有 Gcd(A,B)=1
观察 y2 那个式子,既然 y2,d2 都是完全平方数,那么A和B一定也是完全平方数(在不相等的情况下).
于是我们令 a2=A,b2=B , a2+b2=2rd|a<b
2rd 为一整数,所以d必定是2r的一个因子.
因此从 1 到 2r−−√ 枚举d.
那么只有 2rmodd=0 时才会有答案出现.
注意出现答案时必须满足 A≠B ,A,B互质
我们知道,d是2r的约数有两种情况
①d 此时枚举a从1到 d2−−√ , b=d−a2−−−−−√
② 2rd 枚举a从1到 2r2d−−−√ , b=2rd−a2−−−−−−√
注意每次得到答案要进行检验使得A,B满足条件
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
LL r,ans;
LL gcd(LL a,LL b)
{
return !b?a:gcd(b,a%b);
}
bool pd(LL a,double b)
{
if (floor(b)==b)
{
LL tmpb=(LL)(floor(b));
if (gcd(tmpb*tmpb,a*a)==1&&tmpb*tmpb!=a*a) return 1;
}
return 0;
}
int main()
{
scanf("%lld",&r);
for (LL d=1;d<=(LL)(sqrt(2*r));d++)
{
if (2*r%d==0)
{
for (LL a=1;a<=(LL)(sqrt((2*r)/(2*d)));a++)
{
double b=sqrt(2*r/d-a*a);
if (pd(a,b)) ans++;
}
if (d!=2*r/d)
{
for (LL a=1;a<=(LL)(sqrt(d/2));a++)
{
double b=sqrt(d-a*a);
if (pd(a,b)) ans++;
}
}
}
}
printf("%lld",ans*4+4);
}