前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BZOJ 1041: [HAOI2008]圆上的整点【数论,解方程】

BZOJ 1041: [HAOI2008]圆上的整点【数论,解方程】

作者头像
Angel_Kitty
发布2018-04-09 15:28:12
7090
发布2018-04-09 15:28:12
举报
文章被收录于专栏:小樱的经验随笔

1041: [HAOI2008]圆上的整点

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 4210  Solved: 1908

[Submit][Status][Discuss]

Description

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

Input

只有一个正整数n,n<=2000 000 000

Output

整点个数

Sample Input

4

Sample Output

4

HINT

 科普视频

Source

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1041

【分析】:

样例图示:

首先,最暴力的算法显而易见:枚举x轴上的每个点,带入圆的方程,检查是否算出的值是否为整点,这样的枚举量为2*N,显然过不了全点。

然后想数学方法。

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

枚举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

【时间复杂度分析】:

枚举d:O(sqrt(2R)),然后两次枚举a:O(sqrt(d/2))+O(sqrt(R/d)),求最大公约数:O(logN)

下面给出AC代码:

代码语言:javascript
复制
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 inline ll read()
 5 {
 6     ll x=0,f=1;
 7     char ch=getchar();
 8     while(ch<'0'||ch>'9')
 9     {
10         if(ch=='-')
11             f=-1;
12         ch=getchar();
13     }
14     while(ch>='0'&&ch<='9')
15     {
16         x=x*10+ch-'0';
17         ch=getchar();
18     }
19     return x*f;
20 }
21 inline void write(ll x)
22 {
23     if(x<0)
24     {
25         putchar('-');
26         x=-x;
27     }
28     if(x>9)
29     {
30         write(x/10);
31     }
32     putchar(x%10+'0');
33 }
34 ll gcd(ll a,ll b)
35 {
36     return b==0?a:gcd(b,a%b);
37 }
38 inline bool check(ll y,double x)
39 {
40     if(x==floor(x))//判断整点
41     {
42         ll x1=(ll)floor(x);
43         if(gcd(x1*x1,y*y)==1&&x1*x1!=y*y)//gcd(A,B)==1&&A!=B
44             return true;
45     }
46     return false;
47 }
48 int main()
49 {
50     ll R;
51     R=read();
52     ll ans=0;
53     for(ll d=1;d<=(ll)sqrt(2*R);d++)//1<=d^2<=2R
54     {
55         if((2*R)%d==0)
56         {
57             for(ll a=1;a<=(ll)sqrt(2*R/(2*d));a++)//2*a^2<2*R/d
58             {
59                 double b=sqrt(((2*R)/d)-a*a);
60                 if(check(a,b))
61                     ans++;
62             }
63             if(d!=(2*R)/d)
64             {
65                 for(ll a=1;a<=(ll)sqrt(d/2);a++)//2*a^2<=d
66                 {
67                     double b=sqrt(d-a*a);
68                     if(check(a,b))
69                         ans++;
70                 }
71             }
72         }
73     }
74     printf("%lld\n",ans*4+4);
75     return 0;
76 }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-07-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1041: [HAOI2008]圆上的整点
  • Description
  • Input
  • Output
  • Sample Input
  • Sample Output
  • HINT
  • Source
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档