1041: [HAOI2008]圆上的整点

来源:互联网 发布:阿里云 青岛 编辑:程序博客网 时间:2024/04/29 15:08

数论题无力Orz...看了下题解,所以总结下吧,主要是运用gcd和分解质因数来进行优化。。

觉得写得很好,所以把题解搬过来了=。=

首先让我们一起来推下公式:

x^2+y^2=r^2
    y^2=r^2-x^2
    y^2=(r-x)(r+x)

到这里为止应该都很容易想到,接下来是关键

设d=gcd(r-x,r+x)
设r-x=d*A
  r+x=d*B
  y^2=d^2*AB

解释下,d已被提出,所以gcd(A,B)=1
而进一步,因为y^2=d^2*A*B,而gcd(A,B)=1
所以,我们可以这样表示:
A=a*a
B=b*b
(a<>b)
(因为y^2是平方数,d^2是平方数,所以可以这样化过来)

∴ r-x=d*a^2  
   r+x=d*b^2  

①+②得 2r=d*(a^2+b^2)

d是2r的约数,所以我们可以用sqrt(2r)的时间枚举d,求出好多对d
我们设
d=d
d0=(2r)/d

我们可以用(sqrt(d)+sqrt(d0))的时间来枚举a,求出b,来对这一对d求解

思路应该清晰了吧
下面讲讲细节:
1041: <wbr>[HAOI2008]圆上的整点
我们枚举的其实只是第一象限的答案,而还缺少坐标轴上的4个点
所以最后  ans=ans*4+4  (注意 不是ans*2+4,下面解释)

还有一个细节,在枚举a时实际的枚举范围是 a^2*2<2r/d
我们可以举一个例子
在r=1225中
我们可以算出的其中2个解为
d=490 a=1 b=2
d=490 a=2 b=1
没错,看起来好像a,b倒了一下,不一样
实际算到y中时
y^2=d(a^2+b^2)却成了同一个解
有些题解中最后会是*2而不是*4,就是因为这样(比如当年wjh大神给我们的题解)
这实际是写题解的人自己凑出,没搞清楚,或是没写清造成的

代码什么的就上我自己的好了(格式好乱)

#include<cmath>#include<cstdio>using namespace std;long long r;long long gcd(long long a,long long b){    return b==0?a:gcd(b,a%b);}int cal(int d){    int answer=0;    int d0=r/d;    for(int a=1;a*a*2<=d0;a++)    {        double tmp=sqrt(d0-a*a);        if(tmp==floor(tmp))        {            int b=(int)tmp;            if(gcd(a,b)==1 && a!=b) answer++;        }    }    return answer;}int main(){    int ans=0;    scanf("%d",&r);    r*=2;    for(int i=1;i<=r/i;i++)    {        if(r%i==0)        {            if(r/i!=i)             ans=ans+cal(i)+cal(r/i);            else ans+=cal(i);        }    }    printf("%d",ans*4+4);    return 0;}