【codevs1867】【Tyvj3508】【BZOJ1041】圆上的整点,数学乱搞

传送门1
传送门2
传送门3
写在前面:乱搞数学……
思路:
原博文


有了上面的推理,那么实现的方法为:

枚举d∈[1,sqrt(2R)],然后根据上述推理可知:必先判d是否为2R的一约数。

此时d为2R的约数有两种情况:d=d或d=2R/d。

第一种情况:d=2R/d。枚举a∈[1,sqrt(2R/2d)] <由2*a*a <
2*R/d转变来>,算出对应的b=sqrt(2R/d-a^2),检查是否此时的A,B满足:A≠B且A,B互质
<根据上面的推理可知必需满足此条件>,若是就将答案加1

第二种情况:d=d。枚举a∈[1,sqrt(d/2)] <由2*a*a <
d转变来>,算出对应的b=sqrt(d-a^2),检查是否此时的A,B满足:A≠B且A,B互质
<根据上面的推理可知必需满足此条件>,若是就将答案加1

因为这样只算出了第一象限的情况<上面枚举时均是从1开始枚举>,根据圆的对称性,其他象限的整点数与第一象限中的整点数相同,最后,在象限轴上的4个整点未算,加上即可,那么最后答案为ans=4*第一象限整点数+4

感觉一做数学题就成煞笔了呢……
注意:LL
代码:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL k,r,ans,p,d;
LL gcd(LL x,LL y)
{
    if (y==0) return x;
    return gcd(y,x%y);
}
main()
{
    scanf("%lld",&r);
    k=r<<1; 
    for (int i=1;i<=sqrt(k);i++)
    if (k%i==0)
    {
        d=i;
        for (int j=1;j<=sqrt(r/d);j++)
        {
            p=sqrt(k/d-j*j);
            if (p*p+j*j==k/d&&gcd(p*p,j*j)==1&&p!=j) ans++;
        }
        d=k/i;
        for (int j=1;j<=sqrt(r/d);j++)
        {
            p=sqrt(k/d-j*j);
            if (p*p+j*j==k/d&&gcd(p*p,j*j)==1&&p!=j) ans++;
        }
    }
    printf("%lld",4*ans+4);
}

你可能感兴趣的:(【codevs1867】【Tyvj3508】【BZOJ1041】圆上的整点,数学乱搞)