[HAOI2008]圆上的整点

题面

<center>[HAOI2008]圆上的整点<center>
<center>时间限制:10秒 内存限制:162MB<center>

题目描述
  求一个给定的圆(x^2^+y^2^=r^2^),在圆周上有多少个点的坐标是整数。
输入
  只有一个正整数r,r<=2000 000 000
输出
  整点个数
样例输入

4

样例输出

4

思路

题解
  很简洁的一道题 ,这是我做过所有题里题面最短的一道,也是题意最易理解的一道。但是真正做起来就没那么容易了。这是一道数论题,首先,根据圆的对称性,只需要求处第一象限满足条件的点个数,然后*4,再加上坐标轴上四个满足条件的点就可以了。第一象限满足条件的点,暴力的做法是枚举区间[1,r)内所有的点,判断其是否满足圆的方程,但是由于r最大为2e9,显然会T;所以采取缩小枚举范围的方式进行求解。利用数论基础知识,进行推导从而达到缩小枚举范围的目的,具体推导过程如下:
  x^2^+y^2^=r^2^ $\Rightarrow$ x^2^=r^2^-y^2^=(r+y)*(r-y);
  令d=gcd((r+y),(r-y)),A=$\frac {r+y}{d}$,B=$\frac {r-y}{d}$则gcd(A,B)$\equiv$ 1
  又,x^2^=d^2^*A*B
  $\because$ x^2^、d^2^为完全平方数且gcd(A,B)$\equiv$ 1
  $\therefore$A,B也为完全平方数
  令A=a^2^,B=b^2^,则a^2^+b^2^= $\frac {2*r}{d}$
  通过枚举d $\in$[1,$\sqrt{2*r}$]&d为整数,并使得2*r/d为整数,(d有两种情况:d =d or 2*r/d。分别进行讨论)然后再枚举a(设a<b),a$\in$[1,$\sqrt{2*r/2*d}$],求出b,在b为正整数的情况下,验证A,B是否满足:A$\ne$B&&gcd(A,B)$\equiv$ 1,求出满足条件的点个数就欧克了。

源码

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
int main(){
    ll r,r2;
    cin>>r;r2=2*r;
    ll a,A,B,c,d,ans=4,cnt=0;
    double b;
    for(d=1;d*d<=r2;d++){
        if(r2%d==0){
        c=d;
        ll am=r/c;
        for(a=1;a*a<=am;a++){
            b=sqrt(1.0*r2/d-a*a);
            if(b==(int)b){
                A=a*a;B=b*b;
                if(A!=B&&__gcd(A,B)==1) cnt++;
            }
        }
        c=r2/d;
        if(c!=d){
            am=r/c;
            for(a=1;a*a<=am;a++){
              b=sqrt(1.0*d-a*a);
               if(b==(int)b){
                A=a*a;B=b*b;
                if(A!=B&&__gcd(A,B)==1) cnt++;
            }
        }    
        }    
        } 
    }
    ans+=4*cnt;
    cout<<ans;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值