题面
<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;
}