[HAOI2008]圆上的整点
Description
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
Input
r
Output
整点个数
Sample Input
4
Sample Output
4
HINT
n<=2000 000 000
Solution
x2+y2=r2
y2=(r−x)(r+x)
令d=gcd(r−x,r+x)
y2=d2∗p∗q
因为p,q都是整数,且(p,q)=1
所以
d2|y2,p=u2,q=v2,(u,v)=1
所以
r−x=d∗u2,r+x=d∗v2
解得
2r=d∗(u2+v2)
x=d∗(v2−u2)2,y=duv
枚举d|2r,枚举u<2rd−−√,计算v,判断
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &x){
x=0; T f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-')f=-1; ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
x*=f;
}
const int MaxN=100000;
ll ans=0,r,d[MaxN],tot;
inline ll sqr(ll x){return x*x;}
int main(){
read(r); r<<=1;
for(ll i=1;i*i<=r;i++){
if(r%i==0) d[++tot]=i,d[++tot]=r/i;
if(i*i==r) tot--;
}
for(ll i=1;i<=tot;i++)
for(ll u=1;u*u<r/d[i];u++){
ll v_2=r/d[i]-sqr(u),v=trunc(sqrt(v_2));
if(sqr(1ll*trunc(sqrt(v_2)))==v_2)
if(__gcd(v_2,u*u)==1) ans++;
}
printf("%lld\n",(ans-1)*2+4);
return 0;
}