Bzoj1041--Haoi2008圆上的整点

对于一个半径为n的圆,圆上整点显然是满足x^2+y^2=n^2的x,y的整数解

由于圆的对称性,我们只有考虑第一象限上的整点,最后乘4再加上坐标轴上4个点即为所求

我们将上式变化一下不难得到:

  y^2=n^2-x^2=(n+x)(n-x)

设d为gcd(n+x,n-x),A=(n-x)/d,B=(n+x)/d.

  y^2=d^2*A*B

因为我们只考虑x>0的情况,所以显然A!=B,且因为d为gcd(n+x,n-x),所以gcd(A,B)=1

则有A,B均为完全平方数,不妨设A=a^2,B=b^2。

如果我们将A,B相加可以得到:

  a^2+b^2=(n+x)/d+(n-x)/d=2*n/d

观察上式发现上式成立时2*n必然可以整除d

由此我们可以在sqrt(2n)的时间内去枚举k

对于每个枚举出来的2*n的约数,我们要考虑两个数,即d=k或d=2*n/k。

因为A<B所以显然有a<b

那么a^2+b^2>2*a^2 ==> d>2*a^2 ==> a<sqrt(d/2)

至此,我们只用对于d=k,d=2*n/k分别去枚举a,在算出对应的b是否为整数

之后再回代回上式求出A,B检验一下A,B是否互质即可(避免重复)

代码:

#include<bits/stdc++.h>
#define LL long long
#define MAXN 20000005
using namespace std;

LL n;int ans;

bool check(LL a, LL b) {
    if(__gcd(a,b)==1) return 1;
    else return 0;
}

int main() {
    scanf("%lld",&n);n<<=1;
    int lim=sqrt(n);
    for(int k,t,b,d=1;d<=lim;d++) {
        if(n%d==0) {
            k=sqrt(n/2/d);
            for(int a=1;a<=k;a++) {
                t=n/d-a*a;b=sqrt(t);
                if(b*b==t&&a<b) {
                    t=(b*b-a*a)*d/2;
                    if(check(a*a,b*b)) ans++;
                }
            }
            if(d*d!=n){
                k=sqrt(d/2);
                for(int a=1;a<=k;a++) {
                    t=d-a*a;b=sqrt(t);
                    if(b*b==t&&a<b) {
                        t=(b*b-a*a)*n/d/2;
                        if(check(a*a,b*b)) ans++;
                    }
                }
            }
        }
    }
    printf("%d",ans*4+4);
    return 0;
}

 

posted @ 2016-10-10 16:27  ihopenot  阅读(380)  评论(0编辑  收藏  举报