题意

给定一个圆\(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. C#数组的排序(正序逆序)

    C#数组的排序(正序逆序) 这种排序 超级简单的 ! using System; using System.Collections.Generic; using System.Linq; using ...

  2. CTabCtrl的使用

    1.在主窗口中定义一个CtabCtrl,添加变量m_tabctrl; 2.添加两个子窗口IDD_ONE_DIALOG,IDD_TWO_DIALOG(新建对话框,然后双击界面添加头文件和cpp),属性为 ...

  3. msm8916 lcd 相关调试点指导

    主要代码:LINUX\android\kernel\arch\arm\boot\dts\qcom\dsi-panel-trust-hx8379c-fwvga-video.dtsiLINUX\andro ...

  4. BZOJ 1855 股票交易(单调队列优化DP)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855 题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票 ...

  5. HTML基础 整理

    HTML:超文本传输协议 (Hyper Markup Language) CSS:网页美化 (Cascading Style Sheets) JS:java-scipt 脚本语言 Dreamweave ...

  6. Java中使用BASE64加密&解密

    package com.bao.tools.encryption; import java.io.IOException; import org.junit.Test; import sun.misc ...

  7. ubuntu下mysqli_connect()显示未定义,mysqli_fetch_all()显示未定义 解决方法

    mysqli_connect()显示未定义解决方法: http://www.cnblogs.com/misoag/archive/2013/01/24/2874439.html 让apache.php ...

  8. SQL疑难杂症【1】解决SQL2008 RESTORE 失败问题

    有时候从服务器或者其它电脑上面备份的数据库文件在还原到本地的时候会出现以下错误:  这种情况通常是备份文件之前的逻辑名称跟当前的名称对应不上,我们可以通过以下语句查看备份文件的逻辑名称: 知道备份文件 ...

  9. C# 线程(二):关于线程的相关概念

    From : http://kb.cnblogs.com/page/42528/ 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又 ...

  10. 转 cocos2dx内存优化

    cocos2dx里面,sprite本身不消耗多少内存,只是关联的材质文件消耗内存.假设有10个sprite关联同一个材质,也不会有10倍消耗. 关于图片占用的材质内存,我觉得还有好几种优化手段:1.对 ...