20201016day37 刷题记录
1 [HAOI2008]圆上的整点
problem
给定\(R\),求圆周\(x^2+y^2=R^2\)上整点的个数。整点的定义是点\((a,b),a,b\in\mathbb Z\)
solution
令\(d=\gcd (R+X,R-X)\),则设
\(\because d\)为\(R+X,R-X\)的最大公约数,\(\therefore\)必定存在\(\gcd(A,B)=1\),即\(A⊥ B\)
将\((2)\)代入\((1)\)得
由于\(d^2,Y^2\)一定为完全平方数,则\(A\times B\)必定为一个完全平方数
又因为\(A⊥B,A\neq B\),则\(A,B\)本身都为一完全平方数
\(\therefore\)设\(A\)的算术平方根为\(a\),\(B\)的算术平方根为\(b\),即\(A=a^2,B=b^2\)
由于\(A\neq B,\therefore a\neq b\),令\(a<b\),代入\((2)\),得
\((3)+(4)\)得:
由\((5)\)观察可知:\(2R=Td,T\in \mathbb N_+\),即\(d\)为\(2R\)的一约数
而约数的个数确定,是基于分解质因数<对\(Z\)分解质因数个数最多为\(\sqrt{Z}\)>,则\(1\le d\le \sqrt{2R}\)
有了上面的推理,实现的方法为:
枚举\(d\in \left[1,\sqrt{2R}\right]\),然后根据上述推理可知:必先判断\(d\)是否是\(2R\)的一个约数
此时\(d\)为\(2R\)的约数有两种情况:\(d=\dfrac{2R}{d}\)或\(d=d\)。(如\(d=d\)就是\(d\le \sqrt{2R}\)&&\(\dfrac{2R}{d}\ge \sqrt{2R}\)的情况 )
第一种情况:\(d=\dfrac{2R}{d}\)。枚举\(a∈\left[1,\sqrt{\dfrac{2R}{2d}}\right]\) <由\(2\times a^2 < 2\times\dfrac{R}{d}\)转变来>,算出对应的\(b=\sqrt{\dfrac{2R}{d}}\),检查是否此时的\(A,B\)满足:\(A≠B\)且\(A,B\)互质 <根据上面的推理可知必需满足此条件>,若是就将答案加1
第二种情况:\(d=d\)。枚举\(a∈\left[ 1,\sqrt{\dfrac{d}{2}} \right]\)<由\(2\times a^2< d\)转变来>,算出对应的\(b=\sqrt{d-a^2}\),检查是否此时的\(A,B\)满足:\(A≠B\)且\(A,B\)互质 <根据上面的推理可知必需满足此条件>,若是就将答案加1
因为这样只算出了第一象限的情况<上面枚举时均是从1开始枚举>,根据圆的对称性,其他象限的整点数与第一象限中的整点数相同,最后,在象限轴上的4个整点未算,加上即可,那么最后答案为\(ans=4\times\text{第一象限整点数}+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\n",ans*4+4);
return 0;
}