[bzoj1041] [洛谷P2508] [HAOI2008] 圆上的整点

Description###

求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。

Input###

只有一个正整数n,n<=2000 000 000

Output###

整点个数

Sample Input###

4

Sample Output###

4


想法##

嗯哼,一道数学题。
开始推柿子。

首先我们只需求出满足 $ x^2 + y^2 = z^2 $ 的正整数对数即可,乘以4后再加4便为答案

\[x^2+y^2=z^2 \\ y^2=z^2-x^2=(z+x)(z-x) \\ 设\quad d=gcd(z+x,z-x) \\ 那么 \quad y^2=d^2 \frac{z+x}{d} \frac{z-x}{d} \\ 这里面 \frac{z+x}{d} 与 \frac{z-x}{d} 互质,所以 \frac{z+x}{d} 和 \frac{z-x}{d} 都为完全平方数 \\ 设 \frac{z+x}{d}为A, \frac{z-x}{d}为B \\ 设A=a^2,B=b^2 \\ a^2+b^2=\frac{2z}{d} \\ 故,我们可以枚举2z的每一个约数d,然后再枚举每一对满足a^2+b^2=\frac{2z}{d}的a和b \\ 得到a,b后要带回去算出A,B,判断是否gcd(A,B)=1且A \neq B \]


代码##

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
 
using namespace std;
 
typedef long long ll;
 
ll n,m,ans=0;
ll gcd(ll a,ll b) { return b ? gcd(b,a%b) : a; }
 
int main()
{
    scanf("%d",&n);
    m=sqrt(n*2);
    for(ll d=1;d<=m;d++){
        if((n*2)%d) continue;
        for(ll a=1;a*a*2<=d;a++){
            ll b=sqrt(d-a*a);
            if(b*b!=d-a*a) continue;
            ll A=a*a,B=b*b;
            if(gcd(A,B)!=1 || A==0 || B==0 || A==B) continue;
            ans+=4;
        }
        for(ll a=1;a*a*2<=n*2/d;a++){
            ll b=sqrt(n*2/d-a*a);
            if(b*b!=n*2/d-a*a) continue;
            ll A=a*a,B=b*b;
            if(gcd(A,B)!=1 || A==0 || B==0 || A==B) continue;
            ans+=4;
        }
    }
    printf("%lld\n",ans+4);
     
    return 0;
}
posted @ 2018-04-24 22:35  秋千旁的蜂蝶~  阅读(45)  评论(0编辑  收藏