【bzoj1041】圆上的整点
题意
给定一个圆\(x^2+y^2=z^2\),求圆周上有多少个点的坐标是整数。
\(r\leq 2*10^9\)
分析
这道题目关键要知道一些勾股数的性质,剩下的就很好处理了。
勾股数的性质
参考:勾股数的基本组及其性质
定义1
如果正整数\(a\),\(b\),\(c\)能满足不定方程\(a^2+b^2=c^2\),则它们叫一组勾股数,用\([a,b,c]\)表示。
定义2
如果\([a,b,c]\)为一勾股数组,且\((a,b)=1\),则\([a,b,c]\)叫一个勾股数的基本组;全体勾股数的基本组用集合\(A\)表示。
定义3
若\([a,b,c]\)为一勾股数的基本组,则\([ka,kb,kc]\)叫一勾股数的导出组,其中\(k\in N^+\)
定理1
若\([a,b,c]\in A\),则\((a,b)=(a,c)=(b,c)=(a,b,c)=1\)
定理2
若\([a,b,c]\)为一勾股数组,且\((a,b)=d>1\),则\([a,b,c]\)为一勾股数的导出组。
定理3
若\([a,b,c]\in A\),则\(a\)与\(b\)一奇一偶,\(c\)为奇数。
定理4
一切勾股数的基本组可用下述公式表示:
\(a=2mn,b=m^2-n^2,c=m^2+n^2\),其中\(m,n\)为正整数且\(m>n\),\((m,n)=1\),一奇一偶。
定理5
若\(a^2+b^2=c^2\),\((a,b,c)=(a,b)=(b,c)=(a,c)=1\),则对于\(c-a\)和\(c-b\),一个是完全平方数\(x^2\),一个是完全平方数的两倍\(2y^2\)
思路1:定理5
\(x^2+y^2=r^2\)的整数解的个数,等价于:
①当\(x=0\)或\(y=0\)时,贡献为4;
②当\(x\neq 0\)且\(y\neq 0\)时,由于\((-x)^2=x^2\),所以直接求解正整数解的个数,然后*4即可。
勾股数的组数不多,所以我们要快速求解出所有的勾股数组。
设\(g=\gcd(x,y,r)\),我们枚举所有的\(g\),设\(a={x\over g},b={y\over g},c={r\over g}\),问题转化为求解\(a^2+b^2=c^2\)的基本组\([a,b,c]\)的个数,也就是求\(a^2+b^2=c^2,a>0,b>0,\gcd(a,b)=1\)的解的个数,然后累加答案。
根据定理5,不妨定序,设\(c-a=p^2,c-b=2q^2\),我们枚举所有的\(q\),计算对应的\(a\)和\(b\)。若存在,由于我们进行了定序,所以对答案进行累加为2。
时间复杂度:
\(O(\sqrt r\sum_{d|r}\sqrt d)\)
#include <cstdio>
#include <cmath>
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
typedef long long LL;
int r;
int res;
int gcd(int a,int b)
{
if (!b) return a;
else return gcd(b,a%b);
}
int Check(int a,int b,int c)
{
if (a<1||b<1||c<1) return 0;
if ((LL)a*a+(LL)b*b!=(LL)c*c) return 0;
int g=gcd(a,b);
return g==1;
}
void Solve(int c)
{
int up=(int)sqrt(c/2);
rep(q,1,up)
{
int b=c-2*q*q;
int a=(int)sqrt((LL)c*c-(LL)b*b);
if (Check(a,b,c)) res+=8;
}
}
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("bzoj1041.in","r",stdin);
freopen("bzoj1041.out","w",stdout);
#endif
scanf("%d",&r);
res+=4;
int up=(int)sqrt(r);
rep(g,1,up) if (r%g==0)
{
Solve(r/g); //g=g
if (g*g!=r) Solve(g); //g=r/g
}
printf("%d\n",res);
return 0;
}
思路2:定理4
基本组公式。
根据定理4,
一切勾股数的基本组可用下述公式表示:
\(a=2mn,b=m^2-n^2,c=m^2+n^2\)
和上面一样,只是求\(a^2+b^2=c^2,a>0,b>0,\gcd(a,b)=1\)的解的个数的方法不同。
这里不赘述。
代码更简单,速度也更快。
#include <cstdio>
#include <cmath>
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
int r;
int res;
int gcd(int a,int b)
{
if (!b) return a;
else return gcd(b,a%b);
}
void Solve(int c)
{
int up=(int)sqrt(c/2);
rep(n,1,up)
{
int m=(int)sqrt(c-n*n);
if (m<=n||m*m+n*n!=c) continue;
int a=2*m*n,b=m*m-n*n;
if (gcd(a,b)==1) res+=8;
}
}
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("bzoj1041.in","r",stdin);
freopen("bzoj1041.out","w",stdout);
#endif
scanf("%d",&r);
res+=4;
int up=(int)sqrt(r);
rep(g,1,up) if (r%g==0)
{
Solve(g);
if (g*g!=r) Solve(r/g);
}
printf("%d\n",res);
return 0;
}
小结
(1)要熟记勾股数的这几个性质。
由于证明太过麻烦,时间也不够,就先不看了。
(2)勾股数的个数不多,求解\(x^2+y^2=z^2\)这种不定方程的方法,就是直接利用勾股数的性质加快枚举,找到所有的。
(3)关于代码调试
OI中的代码调试
把数据攻击的方法融入检查的过程中。
【bzoj1041】圆上的整点的更多相关文章
- bzoj1041 圆上的整点 数学
题目传送门 题目大意:求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数. 思路:没思路,看大佬的博客(转载自https://blog.csdn.net/csyzcyj),转载只 ...
- [BZOJ1041]圆上的整点
嗯... 自己看视频讲解? >Click Here< #include<cstdio> #include<queue> #include<iostream&g ...
- 【BZOJ1041】[HAOI2008]圆上的整点
[BZOJ1041][HAOI2008]圆上的整点 题面 bzoj 洛谷 题解 不妨设\(x>0,y>0\) \[ x^2+y^2=r^2\\ y^2=(x+r)(x-r) \] 设\(r ...
- 【BZOJ1041】圆上的整点(数论)
[BZOJ1041]圆上的整点(数论) 题面 BZOJ 洛谷 题解 好神仙的题目啊. 安利一个视频,大概是第\(7\)到\(19\)分钟的样子 因为要质因数分解,所以复习了一下\(Pollard\_r ...
- bzoj千题计划127:bzoj1041: [HAOI2008]圆上的整点
http://www.lydsy.com/JudgeOnline/problem.php?id=1041 设 X>0 ,Y>0 X^2 + Y^2 = R^2 X^2 = R^2-Y^2 ...
- BZOJ1041 [HAOI2008]圆上的整点 【数学】
1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4631 Solved: 2087 [Submit][S ...
- BZOJ 1041: [HAOI2008]圆上的整点
1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3621 Solved: 1605[Submit][Sta ...
- bzoj 1041: [HAOI2008]圆上的整点 数学
1041: [HAOI2008]圆上的整点 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...
- bzoj 1041: [HAOI2008]圆上的整点 本原勾股數組
1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2027 Solved: 853[Submit][Stat ...
- 1041: [HAOI2008]圆上的整点
1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4298 Solved: 1944[Submit][Sta ...
随机推荐
- #define用法集锦
Definition: The #define Directive You can use the #define directive to give a meaningful name to a c ...
- dictionaryWithObjectsAndKeys
NSDictionary dictionaryWithObjectsAndKeys NSDictionary *parmDic = [NSDictionary dictionaryWithObj ...
- SqlSever基础 datepart函数 返回这一秒已经过去了多少毫秒
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- sql server 向oracle导入表
选择相应的数据库,右键,任务,选择导出数据 点击下一步 选择Microsoft OLE DB Provider for Sql Server 选择下一步 目标选择.net Framework data ...
- Create Hierarchical Tree To Control Records In Oracle Forms
Download Source Code Providing an example form for creating hierarchical trees in Oracle Forms to co ...
- RNAseq分析软件STAR的安装
wget https://github.com/alexdobin/STAR/releases/STAR-2.5.2a.tar.gz tar -xzf STAR-2.5.2a.tar.gz cd ST ...
- 《Linux内核设计的艺术》学习笔记(一)从开机加电到加载三个汇编源码
实验内核版本:0.11 ◆ 从开机到main函数的三步: ① 启动BIOS,准备实模式下的中断向量表和中断服务程序: ② 从启动盘加载OS程序到内存中,加载OS程序的工作就是利用第一步中的中断服务 ...
- Sublime Text 2 快捷键用法大全(转)
Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑)Ctrl+G 跳转到相应的行Ctrl+J 合并行(已选择需要合并的多行时)Ctrl+L 选择整行(按住-继续选择下 ...
- [转载] C++11中的右值引用
C++11中的右值引用 May 18, 2015 移动构造函数 C++98中的左值和右值 C++11右值引用和移动语义 强制移动语义std::move() 右值引用和右值的关系 完美转发 引用折叠推导 ...
- [转载] C++ STL string的Copy-On-Write技术
原文: http://coolshell.cn/articles/12199.html stl的string是经过严格优化的, 深入理解对以后编程过程中应用string非常有益处, 感谢左耳朵耗子的精 ...