码迷,mamicode.com
首页 > 其他好文 > 详细

【HAOI2008】【BZOJ1041】圆上的整点

时间:2015-08-28 15:40:14      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:数论

Description

求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。

Input

r

Output

整点个数

Sample Input

4
Sample Output

4
HINT

n<=2000 000 000

Source

不要看见圆就以为是几何QwQ
这题其实TMD是数论啊(╯‵□′)╯︵┻━┻
推公式
x2+y2=r2所以y2=r2?x2=(r+x)(r?x)
可以发现r+xr?x必定存在一个最大公约数为d.
那么y2=d2r+xdr?xd
设后面那两个分式分别为A,B
那么一定有Gcd(A,B)=1
观察y2那个式子,既然y2,d2都是完全平方数,那么A和B一定也是完全平方数(在不相等的情况下).
于是我们令a2=A,b2=B,a2+b2=2rd|a<b
2rd为一整数,所以d必定是2r的一个因子.
因此从12r??枚举d.
那么只有2rmodd=0时才会有答案出现.
注意出现答案时必须满足AB,A,B互质
我们知道,d是2r的约数有两种情况
①d 此时枚举a从1到d2??,b=d?a2?????
2rd 枚举a从1到2r2d???,b=2rd?a2??????
注意每次得到答案要进行检验使得A,B满足条件

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
LL r,ans;
LL gcd(LL a,LL b)
{
    return !b?a:gcd(b,a%b);
}
bool pd(LL a,double b)
{
    if (floor(b)==b)
    {
        LL tmpb=(LL)(floor(b));
        if (gcd(tmpb*tmpb,a*a)==1&&tmpb*tmpb!=a*a)  return 1;
    }
    return 0;
}
int main()
{
    scanf("%lld",&r);
    for (LL d=1;d<=(LL)(sqrt(2*r));d++)
    {
        if (2*r%d==0)
        {
            for (LL a=1;a<=(LL)(sqrt((2*r)/(2*d)));a++)
            {
                double b=sqrt(2*r/d-a*a);
                if (pd(a,b))    ans++;
            }
            if (d!=2*r/d)
            {
                for (LL a=1;a<=(LL)(sqrt(d/2));a++)
                {
                    double b=sqrt(d-a*a);
                    if (pd(a,b))    ans++;
                }
            }
        }
    }
    printf("%lld",ans*4+4);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

【HAOI2008】【BZOJ1041】圆上的整点

标签:数论

原文地址:http://blog.csdn.net/creationaugust/article/details/48052329

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!