zoukankan      html  css  js  c++  java
  • poj 1305 (毕达哥拉斯三元组,构造勾股数)

    Fermat vs. Pythagoras
    Time Limit: 2000MS   Memory Limit: 10000K
    Total Submissions: 1427   Accepted: 831

    Description

    Computer generated and assisted proofs and verification occupy a small niche in the realm of Computer Science. The first proof of the four-color problem was completed with the assistance of a computer program and current efforts in verification have succeeded in verifying the translation of high-level code down to the chip level. 
    This problem deals with computing quantities relating to part of Fermat's Last Theorem: that there are no integer solutions of a^n + b^n = c^n for n > 2. 
    Given a positive integer N, you are to write a program that computes two quantities regarding the solution of x^2 + y^2 = z^2, where x, y, and z are constrained to be positive integers less than or equal to N. You are to compute the number of triples (x,y,z) such that x < y < z, and they are relatively prime, i.e., have no common divisor larger than 1. You are also to compute the number of values 0 < p <= N such that p is not part of any triple (not just relatively prime triples). 

    Input

    The input consists of a sequence of positive integers, one per line. Each integer in the input file will be less than or equal to 1,000,000. Input is terminated by end-of-file

    Output

    For each integer N in the input file print two integers separated by a space. The first integer is the number of relatively prime triples (such that each component of the triple is <=N). The second number is the number of positive integers <=N that are not part of any triple whose components are all <=N. There should be one output line for each input line.

    Sample Input

    10
    25
    100
    

    Sample Output

    1 4
    4 9
    16 27
    

    Source

    题意是说,能构造多少本元勾股数和勾股数,要求构造的数<=n

    所谓本元勾股数,就是三个勾股数没有公因数,两两互质。

    由本元勾股数扩大k倍,就可以得到其他勾股数。

    而构造本元勾股数的方法如下:

    a=s*t,b=(s^2-t^2)/2,c=(s^2+t^2)/2

    其中s>t>=1是任意没有公因数的奇数!

    引用一段构造正确性的证明:

    本原勾股数组(PPT)是一个三元组(a,b,c),其中a,b,c无公因数,且满足a² +b² =c²。

    很明显存在无穷多个勾股数组(abc同乘以n),下面研究abc没有公因数的情况,先写出一些本原勾股数组:

    case:(3,4,5) (5,12,13) (8,15,17) (7,24,25) (20,21,29)(9,40,41)(12,35,37)(11,60,61)(28,45,53) (33,56,65) (16,63,65)

    观察可以看出a,b奇偶性不同且c总是奇数。(用一点技巧可以证明这是正确的)

    3² = 5² - 4² = (5-4)(5+4) = 1 × 9

    15² = 17²-8² = (17-8)(17+8) = 9 ×25

    35² = 37² - 12² = (37-12)(37+12) = 25 ×49

    ......

    很神奇的是似乎c-b与c+b总是平方数,并且c-b与c+b木有公因数。证明一下下:假设有公因数,设d是c-b与c+b的公因数,则d也整除(c+b)+(c-b)=2c, (c+b)-(c-b) = 2b,所以d整除2c,2b,但是b,c木有公因数,又假设了(a,b,c)是本原勾股数组,从而d等于1或2,又因为d整除(c-b)(c+b)=a².a²是奇数,所以d = 1,c-b与c+b木有公因数。,又因为(c-b)(c+b)=a²,所以c-b与c+b的积是平方数,只有二者都是平方数才会出现(可以把二者分解成素数乘积直观地看出),令c+b = s²,c-b=t²,解得

    c=(s²+t²)/2, b=(s²-t²)/2,a = √(c-b)(c+b) = st.这就得出了勾股数组定理:

    每个本原勾股数组(a,b,c)(a为奇数,b偶数)都可由如下公式得出:a=st,b=(s²-t²)/2, c = (s²+t²)/2, 其中s>t>=1是没有公因数的奇数。

    当取t=1时就可以得到上面的许多例子。


    /*************************************************************************
        > File Name: code/poj/1305.cpp
        > Author: 111qqz
        > Email: rkz2013@126.com 
        > Created Time: 2015年08月22日 星期六 13时49分30秒
     ************************************************************************/
    
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<map>
    #include<set>
    #include<queue>
    #include<vector>
    #include<stack>
    #define y0 abc111qqz
    #define y1 hust111qqz
    #define yn hez111qqz
    #define j1 cute111qqz
    #define tm crazy111qqz
    #define lr dying111qqz
    using namespace std;
    #define REP(i, n) for (int i=0;i<int(n);++i)  
    typedef long long LL;
    typedef unsigned long long ULL;
    const int inf = 0x3f3f3f3f;
    const int N= 1E6+7;
    bool v[N];
    int n;
    int gcd(int a,int b){
        if (a<b) return gcd(b,a);
        if (a%b==0) return b;
        return gcd(b,a%b);
    }
    int main()
    {
        while (scanf("%d",&n)!=EOF){
        memset(v,false,sizeof(v));
        int ans = 0 ;
        int cnt = 0 ;
        for ( int t = 1 ; t <= n ;t = t + 2){
            for ( int s = t+2 ; s*t<= n; s = s + 2){
            if (gcd(s,t)==1){
                int a = s*t;
                int b = (s*s-t*t)/2;
                int c = (s*s+t*t)/2;
                if (a<=n&&b<=n&&c<=n){
                ans++;
                for ( int i = 1 ; i*a<=n&&i*b<=n&&i*c<=n;i++){
                    v[i*a] = true;    
                    v[i*b] = true;
                    v[i*c] = true;
                }
                }
            }
            }
        }
        for ( int i = 1 ; i <= n ; i++){
            if (!v[i]) cnt++;
        }
        printf("%d %d
    ",ans,cnt);
        }
        return 0;
    }
  • 相关阅读:
    JS 正则查找与替换
    MySQL 批量插入值
    Python/Django 批量下载Excel
    Python/Django 下载Excel2007
    Python/Django 下载Excel2003
    Python3安装Scrapy
    服务器响应状态码
    细说同域-同父域-跨域
    细说Ajax跨域
    PostgreSQL学习
  • 原文地址:https://www.cnblogs.com/111qqz/p/4750191.html
Copyright © 2011-2022 走看看