测试公式的显示~

problem

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

Input

只有一个正整数r,r<=2000 000 000

Output

整点个数

Sample Input

4

Sample Output

4

Hint

科普视频

思路

显然,对于所给半径r,对应四个坐标轴上的点一定在圆 x2+y2=r2 x 2 + y 2 = r 2 上;而对于四个象限内的坐标,问题转化为求解二次方程 x2+y2=r2 x 2 + y 2 = r 2 的整数解,其中 x>0,y>0 x > 0 , y > 0 。记所得解组数为n,由对称性则ans=(n+1)*4

x2+y2=r2 x 2 + y 2 = r 2 方程有多少组整数解?,其中r的范围为 2109 2 ∗ 10 9

易想到的做法是对x进行 [1,r22] [ 1 , r 2 2 ] 的枚举,判断是否存在y,y∈ N+ N + 满足方程。

但注意到r的范围,这种方法会超时。


下面这种方法,利用了互质数的特殊性质,可以将等式简化,从而降低复杂度

xx+yy=r2y2=r2x2=(r+x)(rx)d=gcd(r+x,rx),gcd(r+xd,rxd)=1 设 x ∗ x + y ∗ y = r 2 则 y 2 = r 2 − x 2 = ( r + x ) ( r − x ) 设 d = g c d ( r + x , r − x ) , 则 g c d ( r + x d , r − x d ) = 1

A=r+xd,B=rxd 记 A = r + x d , B = r − x d ,即A,B是互质的。我们利用同除以gcd的方法构造出了互质的两个数A,B ,将其带入上面*式,则得 ABd2=y2,AB=(yd)2 A ∗ B ∗ d 2 = y 2 , A ∗ B = ( y d ) 2 ,又由于d|y(因为r+x,r-x中都含有d这个因子),所以得到 AB A ∗ B 为完全平方数。又因为A,B是互质的,所以A,B本身都是完全平方数。(下面给出这个性质的证明)


已知两个数A,B是互质的,且 AB=C2,C A ∗ B = C 2 , C 为 整 数 ,则A,B本身都是完全平方数

证明:由于A,B是互质的,则分解质因数后,他们不含有公共的因数 p p 。A,B相乘,由于没有相同的底数,则相当于把两个质因数直接“拼接”在一起。而现在这个数是完全平方数,即每个指数都是偶数,因此原先A,B质因子分解的每个指数也是偶数。得证。


接着这题,设A=a2,B=b2,因此 a2+b2=2rd a 2 + b 2 = 2 r d 。因此只有当d|2r时,这个等式才有解,也就等价于 xx+yy=r2 x ∗ x + y ∗ y = r 2 有解。所以我们枚举 {d|d|2r} { d | d | 2 r } ,得到2r的两个因子(一大一小,成对出现),记为x,y。再去解方程 a2+b2=xa2+b2=y a 2 + b 2 = x a 2 + b 2 = y 即可(解这两个方程用普通根号折中枚举方法)。

总的复杂度约为 O(2r[O(d2)+O(rd)] O ( 2 r 常 数 ) ∗ [ O ( d 2 ) + O ( r d ) ] ,其中常数的大小由r的因子数决定。

代码示例

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

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

bool judge_Coprime(ll a,ll b)
{
    if(gcd(a,b)==1&&a!=b) return true;
    else return false;
}

int main()
{
    ios::sync_with_stdio(false);
    ll r;
    cin>>r;
    ll ans=0;
    for(ll d=1;d<=(ll)sqrt(2*r);++d){
        if(2*r%d==0){
           // cout<<"d是"<<d<<": ";
            for(ll b=1;b<=(ll)sqrt(d*1.0/2.0);++b){
                ll a=(ll)sqrt(d-b*b);
                    //cout<<"① a、b是: "<<a<<' '<<b<<endl;
                if((a*a+b*b==d)&&(judge_Coprime(a,b)==1))  ans++;
            }
            for(ll b=1;b<=(ll)sqrt(r*1.0/d);++b){
                ll a=(ll)sqrt(2*r*1.0/d-b*b);
                    //cout<<"② a、b是: "<<a<<' '<<b<<' '<<endl;
                if((a*a+b*b==2*r/d)&&(judge_Coprime(a,b)==1)) ans++;
            }
        }
    }

    cout<<4*(ans+1)<<endl;

    return 0;
}

总结

两个互质的数相乘为一完全平方数,则这两个数为完全平方数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值