首页 > 代码库 > Bzoj1041--Haoi2008圆上的整点

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 20000005using 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;}

 

Bzoj1041--Haoi2008圆上的整点