1 [HAOI2008]圆上的整点
problem
给定(R),求圆周(x^2+y^2=R^2)上整点的个数。整点的定义是点((a,b),a,binmathbb Z)
solution
令(d=gcd (R+X,R-X)),则设
(ecause d)为(R+X,R-X)的最大公约数,( herefore)必定存在(gcd(A,B)=1),即(A⊥ B)
将((2))代入((1))得
由于(d^2,Y^2)一定为完全平方数,则(A imes B)必定为一个完全平方数
又因为(A⊥B,A
eq B),则(A,B)本身都为一完全平方数
( herefore)设(A)的算术平方根为(a),(B)的算术平方根为(b),即(A=a^2,B=b^2)
由于(A
eq B, herefore a
eq b),令(a<b),代入((2)),得
((3)+(4))得:
由((5))观察可知:(2R=Td,Tin mathbb N_+),即(d)为(2R)的一约数
而约数的个数确定,是基于分解质因数<对(Z)分解质因数个数最多为(sqrt{Z})>,则(1le dle sqrt{2R})
有了上面的推理,实现的方法为:
枚举(din left[1,sqrt{2R}
ight]),然后根据上述推理可知:必先判断(d)是否是(2R)的一个约数
此时(d)为(2R)的约数有两种情况:(d=dfrac{2R}{d})或(d=d)。(如(d=d)就是(dle sqrt{2R})&&(dfrac{2R}{d}ge sqrt{2R})的情况 )
第一种情况:(d=dfrac{2R}{d})。枚举(a∈left[1,sqrt{dfrac{2R}{2d}} ight]) <由(2 imes a^2 < 2 imesdfrac{R}{d})转变来>,算出对应的(b=sqrt{dfrac{2R}{d}}),检查是否此时的(A,B)满足:(A≠B)且(A,B)互质 <根据上面的推理可知必需满足此条件>,若是就将答案加1
第二种情况:(d=d)。枚举(a∈left[ 1,sqrt{dfrac{d}{2}} ight])<由(2 imes a^2< d)转变来>,算出对应的(b=sqrt{d-a^2}),检查是否此时的(A,B)满足:(A≠B)且(A,B)互质 <根据上面的推理可知必需满足此条件>,若是就将答案加1
因为这样只算出了第一象限的情况<上面枚举时均是从1开始枚举>,根据圆的对称性,其他象限的整点数与第一象限中的整点数相同,最后,在象限轴上的4个整点未算,加上即可,那么最后答案为(ans=4 imes ext{第一象限整点数}+4)
【时间复杂度分析】枚举(d):(O(sqrt(2R))),然后两次枚举a:O(sqrt(d/2))+O(sqrt(R/d)),求最大公约数:O(logN)
code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL R,ans=0;
LL gcd(LL x,LL y){
if(x%y==0) return y;
else return gcd(y,x%y);
}
bool check(LL y,double x)
{
if(x==floor(x))//判断整点
{
LL x1=(LL)floor(x);
if(gcd(x1*x1,y*y)==1 && x1*x1!=y*y)//gcd(A,B)=1并且A!=B
return true;
}
return false;
}
int main()
{
scanf("%lld",&R);
for(LL d=1;d<=(LL)sqrt(2*R);d++)
{
if((2*R)%d==0)
{
for(LL a=1;a<=(LL)sqrt(2*R/(2*d));a++)//2*a^2<2*r/d
{
double b=sqrt(((2*R)/d)-a*a);
if(check(a,b))
ans++;
}
if(d!=(2*R)/d)
{
for(LL a=1;a<=(LL)sqrt(d/2);a++)//2*a^2<d
{
double b=sqrt(d-a*a);
if(check(a,b))
ans++;
}
}
}
}
printf("%lld
",ans*4+4);
return 0;
}