题意

给定一个圆\(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】圆上的整点的更多相关文章

  1. bzoj1041 圆上的整点 数学

    题目传送门 题目大意:求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数. 思路:没思路,看大佬的博客(转载自https://blog.csdn.net/csyzcyj),转载只 ...

  2. [BZOJ1041]圆上的整点

    嗯... 自己看视频讲解? >Click Here< #include<cstdio> #include<queue> #include<iostream&g ...

  3. 【BZOJ1041】[HAOI2008]圆上的整点

    [BZOJ1041][HAOI2008]圆上的整点 题面 bzoj 洛谷 题解 不妨设\(x>0,y>0\) \[ x^2+y^2=r^2\\ y^2=(x+r)(x-r) \] 设\(r ...

  4. 【BZOJ1041】圆上的整点(数论)

    [BZOJ1041]圆上的整点(数论) 题面 BZOJ 洛谷 题解 好神仙的题目啊. 安利一个视频,大概是第\(7\)到\(19\)分钟的样子 因为要质因数分解,所以复习了一下\(Pollard\_r ...

  5. 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 ...

  6. BZOJ1041 [HAOI2008]圆上的整点 【数学】

    1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4631  Solved: 2087 [Submit][S ...

  7. BZOJ 1041: [HAOI2008]圆上的整点

    1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3621  Solved: 1605[Submit][Sta ...

  8. bzoj 1041: [HAOI2008]圆上的整点 数学

    1041: [HAOI2008]圆上的整点 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...

  9. bzoj 1041: [HAOI2008]圆上的整点 本原勾股數組

    1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2027  Solved: 853[Submit][Stat ...

  10. 1041: [HAOI2008]圆上的整点

    1041: [HAOI2008]圆上的整点 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4298  Solved: 1944[Submit][Sta ...

随机推荐

  1. 改变HTML

    改变HTML 1.改变HTML输出流 JavaScript可以创建动态的HTML内容.(注意:不要在加载文档后使用document.write(),这会覆盖文档.) <%@ page langu ...

  2. IIS7多域名绑定同一物理目录,设置不同默认文档的解决方案

    转载自 http://zzstudy.offcn.com/archives/6159 如何解决IIS7多域名绑定同一物理目录,设置不同的默认文档的问题? 因为在一个物理目录下只有一个web.confi ...

  3. Cacti中文版在Centos上的安装

    最近老有人问Cacti中文版在哪下载啊怎么安装啊,我在这里一遍给大家讲解了:Cacti中文版在Centos上的安装 1.基本安装 cacti是运作在apache+php+mysql+net-snmp工 ...

  4. 【Unity3D游戏开发】性能优化之spine提高80~90%的效率 (三一)

    Spine效率低 Unity项目加载spine动画,经常会出现卡顿的情况,如游戏中瞬间播放一个动画,打开一个带spine动画的界面.尤其是SkeletonRenderer.Awake时,会瞬间出现大量 ...

  5. Python操作文件、文件夹、字符串

    Python 字符串操作 去空格及特殊符号 s.strip().lstrip().rstrip(',') 复制字符串 #strcpy(sStr1,sStr2) sStr1 = 'strcpy' sSt ...

  6. 反弹SHELL汇总

    http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet Reverse Shell Cheat Sheet If y ...

  7. CUBRID学习笔记 38 net调用java的函数过程

    首先要设置java_stored_procedure 为yes  该配置项在cubrid.conf中 书写并编译java代码 public class SpCubrid{      public st ...

  8. Installing Python 3.5.2 from source

    Here are the procedures we are to follow, Download the source code of an official Python release. Co ...

  9. implement "slam_karto" package on a Freight robot

    1. login ssh fetch@<robot ip or robot name> 2.  set robot master modify .bashrc in robot's com ...

  10. C# 超时类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...