圆上的整点

#[BZOJ1041][HAOI2008] 圆上的整点

给定一个圆 $x^2+y^2=r^2,r\text{ 为整数}$ ,求在圆周上有多少个点的坐标是整数。

$n\leq2\times10^8$

其实这不是计算几何,而是数论。
$$
x^2+y^2=r^2\
\implies y=\sqrt{(r+x)(r-x)}
$$

令 $d=gcd(r+x,r-x)$, 设 $\displaystyle A=\frac{r-x}{d},B=\frac{r+x}{d}$
则 $gcd(A,B)=1$, 即 $A,B$ 互质.

回带得 $y^2=d^2\cdot A\cdot B$
由于 $d^2,y^2$ 为完全平方数 , 则 $A\cdot B$ 为完全平方数;
又 $gcd(A,B)=1$, 排除 $A=B$ 的情况 , 说明 $A,B$ 均为完全平方数.

设 $A=a^2,B=b^2$

$$
a^2=\frac{r-x}{d},b^2=\frac{r+x}{d}\
\implies a^2+b^2=\frac{2r}{d}
$$
观察可知: $d$ 为 $2R$ 的一约数,则 $1\leq d\leq\sqrt{2r}$

具体统计的思路是枚举可能的 $a,b$ 看是否满足 $gcd(A,B)=1$.

我们先枚举 $d\in[1,\sqrt{2r}],d\mid 2r$;
然后对于每一个满足条件的 $d$ 我们就找到了两个约数 $\displaystyle d,\frac{2r}{d}$:

  • 枚举 $\displaystyle a\in[1,\sqrt{\frac{r}{d}}]$ (不妨设 $a<b$ ,则 $\displaystyle 2a^2\leq\frac{2r}{d}$) ,则 $\displaystyle b=\sqrt{\frac{2r}{d}-a^2}$ ,判断并统计答案;
  • 枚举 $\displaystyle a\in[1,\sqrt{\frac{d}{2}}]$ ($2a^2\leq d$), 则 $b=\sqrt{d-a^2}$, 判断并更新答案.

那么我们已经求出了一个象限的圆上整点数 $res$ 了,根据圆的对称性,再统计上坐标轴上的 $4$ 个整点,答案就是 $res*4+4$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
#include<cstdio>
#include<cmath>
typedef long long ll;

ll R,ans=0;

ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}

bool check(ll y,double x)
{
if(x==std::floor(x))
{
ll x1=(ll)floor(x);
if(gcd(x1*x1,y*y)==1&&x1*x1!=y*y)
return true;
}
return false;
}
int main()
{
scanf("%lld",&R);
for(ll d=1;d*d<2*R;d++)
if((2*R)%d==0)
{
for(ll a=1;a*a<=2*R/(2*d);a++)
{
double b=std::sqrt(2*R/d-a*a);
if(check(a,b)) ans++;
}
if(d!=2*R/d)
for(ll a=1;a*a<=d/2;a++)
{
double b=sqrt(d-a*a);
if(check(a,b)) ans++;
}
}
printf("%lld\n",ans*4+4);
return 0;
}