[HAOI2008]圆上的整点(数论)

题意:传送门

题解:可以先看下这个视频传送门

这个题根据视频可以得到点启示,接着推导下,参考博客:传送门

首先可以写出x^2+y^2=R^2

接着继续写出:Y^2=R^2-X^2

y^2=(R+X)*(R-X)

Y=\sqrt{(R+X)(R-X)}

我们令d=gcd(R+X,R-X)

接着再令A=(R-X)/d

B=(R+X)/d

那么可以得到X^2=A*B*d^2

扫描二维码关注公众号,回复: 4986109 查看本文章

因为X^2和d^2都是完全平方数,那么A*B也是完全平方数,又因为A,B相互互质,所以A是完全平方数,B是完全平方数

那么再令a*a=(R-X)/d=A

b*b=(R+X)/d=B

所以a<b

得到a^2+b^2=2*R/d

然后先开始枚举2*R的约数,因为枚举约数最多只需要枚举到sqrt(2*R),两边的约数就都可以得到了(此处需要多想下),然后进行枚举a,推出b,进行特判(特判条件如上),之后答案累加,因为我们只是枚举了,第一象限里的,之后需要乘上4再加上四。

附上代码:


#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

ll r;

ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}

bool check(ll a,ll b)
{
    if(gcd(b,a)==1){
        return true;
    }
    return false;
}

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

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/86476953