luogu2508 [HAOI2008]圆上的整点
Posted headboy2002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu2508 [HAOI2008]圆上的整点相关的知识,希望对你有一定的参考价值。
题目大意
给出$r$,求圆$x^2+y^2=r^2$上坐标均为整数的点数。$n<=2,000,000,000$
总体思路
我们看到这个数据大小,还是个数学题,想到这个的时间复杂度应当为$O(\sqrt{r})$。要达到这个效果,我们先要把$r^2$转化成$r$,然后在$\sqrt{r}$的范围内枚举某个数。对于我们以前的经验,这枚举的“某个数”有:质因数分解、求因数等。这个题目好像跟质数的关系不大!那就是枚举因数喽!
以上的叙述就为我们以后的数学推导提供了目标。推导时,应当思维发散,大胆尝试,多尝试几种方法,最终筛选出以下数学推导得出解决办法的过程。
数学推导
经过移项等操作我们得到:
$$y^2=(r-x)(r+x)$$
我们令$d=\gcd(r+x,r-x)$,$A=\frac{r-x}{d},B=\frac{r+x}{d}$。这时我们发现:
$$A+B=\frac{2r}{d}$$
这样,我们在$\sqrt{2r}$内枚举$d$(同时得到了$d$一个因数和$\frac{2r}{d}$一个因数),再在$2r/d/2=\frac{r}{d}$内枚举$A$和$B$,看看有多少对$A,B$符合要求。这样我们已经把$r$降次了。
但是我们仍然可以进一步优化。
推论1
对$a,b,c\in Z$,若$a^2=b^{2}c$,则$\sqrt{c}\in Z$.
证明:$c=(\frac{a}{b})^2, b^2|a^2$
推论2
对$a,b,c\in Z$,若$a^2=bc$,且$\gcd(b,c)=1$,则$\sqrt{b}\in Z, \sqrt{c}\in Z$
证明:因为$b,c$互质,故根据唯一分解定理,$b,c$的质因数中不存在交集。因为$a$是个完全平方数,组成它的所有质因数的次数都是偶数,而这些质因数都必须存在于$b,c$中,因此原命题成立。
这样,因为$y^2=d^2AB$,故根据推论1,$AB$为完全平方数。因为$\gcd(A,B)=1$,所以根据结论2,$A,B$为完全平方数。所以,为了保证枚举到的$A$都是完全平方数,令$a=\sqrt{A},b=\sqrt{B}$,看看是否能同时满足存在整数$b$使得$a^2+b^2=\frac{2r}{d}$且$a+b\gcd(A=a^2,B=b^2)=1$。这样$a$枚举的范围便是$\sqrt\frac{r}{d}$,进一步加快了速度。
#include <cstdio>
#include <cmath>
using namespace std;
#define ll long long
ll Gcd(ll a, ll b)
{
return b ? Gcd(b, a%b) : a;
}
void Find(ll r, ll d, ll &ans)
{
for (ll a = 1; a <= sqrt(r / d); a++)
{
ll b = sqrt(r * 2 / d - a * a);
if (a * a + b * b == r * 2 / d && a != b && Gcd(a * a, b * b) == 1) ans++;
}
}
int main()
{
ll r, ans = 0;
scanf("%lld", &r);
for (ll d = 1; d * d <= r * 2; d++)
{
if (r * 2 % d == 0)
{
Find(r, d, ans);
if (d*d != r * 2)
Find(r, r * 2 / d, ans);
}
}
printf("%lld\n", ans * 4 + 4);
return 0;
}
以上是关于luogu2508 [HAOI2008]圆上的整点的主要内容,如果未能解决你的问题,请参考以下文章