Description
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
Input
只有一个正整数n,n<=2000 000 000
Output
整点个数
Sample Input
4
Sample Output
4
这种题肯定是要推柿子的啦~~~
(X^2+Y^2=R^2)
(Y^2=(R-X)(R+X))
令(d=gcd(R-X,R+X),A=dfrac{R-X}{d},B=dfrac{R+X}{d})
所以(y^2=d^2 imes A imes B)
因为(y^2,d^2)为完全平方数,因此(A imes B)也为完全平方数
由于(gcd(A,B)=1),因此(A,B)本身也是完全平方数
令(a^2=A,b^2=B),由于(gcd(A,B)=1),因此(A e B),因此(a e b)
我们令(a<b),则可以得到(a^2=dfrac{R-X}{d},b^2=dfrac{R+X}{d})
相加可得(a^2+b^2=dfrac{2R}{d}),因此(d)为(2R)的约数
于是我们可以在(sqrt{2R})的时间内枚举其约数,由于(2a^2<dfrac{2R}{d}),因此我们可以直接枚举(ain[1,sqrt{dfrac{R}{d}}]),然后计算出(b),再将其反代回求出(A,B),判断(A,B)是否满足条件
但是这样子我们只算出了处于第一象限的答案,根据圆的对称性,我们需要将答案乘上4,并且加上坐标轴上的4个点
/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
int x=0,f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline int read(){
int x=0,f=1; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
}
ll R,Ans;
ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
bool check(int a,int b){
ll A=1ll*a*a,B=1ll*b*b;
return (gcd(A,B)==1)&&(A!=B);
}
void work(ll x){
for (int a=1;a*a<=x>>1;a++){
int b=trunc(sqrt(x-a*a));
if (1ll*a*a+1ll*b*b!=x) continue;
if (check(a,b)) Ans++;
}
}
int main(){
R=2ll*read();
for (int i=1;1ll*i*i<=R;i++){
if (R%i) continue;
work(i);
if (R/i!=i) work(R/i);
}
printf("%lld
",4*Ans+4);
}