【HAOI2008】【BZOJ1041】圆上的整点

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=r2x2=(r+x)(rx)
可以发现 r+x rx 必定存在一个最大公约数为d.
那么 y2=d2r+xdrxd
设后面那两个分式分别为A,B
那么一定有 Gcd(A,B)=1
观察 y2 那个式子,既然 y2,d2 都是完全平方数,那么A和B一定也是完全平方数(在不相等的情况下).
于是我们令 a2=A,b2=B , a2+b2=2rd|a<b
2rd 为一整数,所以d必定是2r的一个因子.
因此从 1 2r 枚举d.
那么只有 2rmodd=0 时才会有答案出现.
注意出现答案时必须满足 AB ,A,B互质
我们知道,d是2r的约数有两种情况
①d 此时枚举a从1到 d2 , b=da2
2rd 枚举a从1到 2r2d , b=2rda2
注意每次得到答案要进行检验使得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);
}

你可能感兴趣的:(数论)