[HAOI2008]圆上的整点
[HAOI2008]圆上的整点
题目链接:链接
思路
这道题目,我们先想一想怎么做暴力?我们可以暴力枚举所有点的横坐标,由于这些整数点的横坐标不能超过$2*r$,所以枚举横坐标的时间复杂度是$O(2*r)$,验证的是$O(1)$,总时间复杂度,过不了。
暴力想到了,我们就要开始想正解了,仔细读题(题目中给的视频可以看一看,视频做的不错),我们可以发现一个他给的式子$x^2+y^2=r^2$,我们可以由这个式子进行推导,过程如下:
$x^2+y^2=r^2$ $\Rightarrow$ $x^2=r^2-y^2 \Rightarrow$ $x^2=(r-y)*(r+y) \Downarrow$
我们设$d=gcd(r-y,r+y) \Rightarrow$ $x^2=(d*\frac{(r-y)}{d})*(d*\frac{(r+y)}{d})\Downarrow$
我们再设$A=\frac{(r-y)}{d}$ $B=\frac{(r+y)}{d} \Rightarrow$ $x^2=d^2*A*B$
我们看,这个式子的左边是平方,右面是一个平方乘上两个互质的数,所以不难想到,这两个数都是两个平方。所以我们可以把$A$替换成$a^2$,把$B$替换成$b^2$,这样式子就变成了$x^2=d^2*a^2*b^2$这个样子。我们再看以前对于$A$和$B$的定义,我们可以看到$a^2=\frac{r-y}{d}$和$b^2=\frac{r+y}{d}$,这样我们就可以看出来一个性质,$a^2+b^2=\frac{2*r}{d}$,如果我们能够知道$d$和$a$之后$O(1)$推出$b$的值,是不是很好?
既然推出这个式子来了,我们很容易能看出来这是一个枚举题目,我们可以枚举d的值,由于$a^2+b^2=\frac{2*r}{d}$,我们可以知道$d$一定是$2*r$的一个约数,所以我们需要用$O(\sqrt{n})$,来枚举$d$的值,再知道一个$d$的值的前提下,我们再用上方的式子,来枚举$a$的值,同时求出$b$的值验证,验证有三条:$b$是否为整数;$b$是否和枚举的$a$互质;$a\neqb$。这三个条件如果都满足,则答案加一。由于我们只是枚举了$a<b$的情况,所以我们这只是统计了在第一象限上的点的个数,所以得到的结果要乘以四,又因为我们没有计算坐标轴上的点,且有四个,所以还要加上四。
代码
#include <stdio.h> #include <math.h> long long n; long long ans; long long gcd(long long x,long long y) { if(!y) return x; return gcd(y,x%y); } int main() { scanf("%lld",&n); for(long long i=1;i*i<=2*n;i++) { if((2*n)%i) continue; for(long long a=1;a*a<=i/2;a++) { long long b=sqrt(i-a*a); if(b*b+a*a!=i) continue; if(gcd(a,b)!=1||a==b) continue; ans++; } for(long long a=1;a*a<=(2*n)/(2*i);a++) { long long b=sqrt(2*n/i-a*a); if(b*b+a*a!=2*n/i) continue; if(gcd(a,b)!=1||a==b) continue; ans++; } } printf("%lld",ans*4+4); }