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
到
那么只有
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);
}