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

Description

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

Input

只有一个正整数 (n) , (n leq 2000000000)

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 eq 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
",ans+4);
     
    return 0;
}
既然选择了远方,便只顾风雨兼程
原文地址:https://www.cnblogs.com/lindalee/p/8934217.html