UVa 106 - Fermat vs. Pythagoras 素勾股数
来源:互联网 发布:淘宝美工工资怎么算 编辑:程序博客网 时间:2024/04/30 02:08
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=42&mosmsg=Submission+received+with+ID+13714821
题目大意:
给你一个N,计算出1-N内所有的勾股数,要求a和b和c互质,同时计算p,p表示1-N中不能构成勾股数的数字的个数,其中没有互质的也算,比如6,8,10也算算,如果N是10,那么p就是4。
由于给的N的范围是1000000以内,所以用普通的枚举的方法肯定会TLE的,所以需要进行优化。
首先考虑平方数的性质,对于一个奇数(2n+1),(2n+1)^2 = 4(n^2 + n) + 1,所以 (2n+1)^2 = 1 (mod 4).
对于一个偶数(2n),(2n)^2 = 4n^2,所以(2n)^2 = 0 (mod 4)。
所以如果一个数要是平方数,那么这个数肯定mod 4余一或者余零。
首先,x,y互质,所以x和y中至少有一个奇数。考虑上面说过的平方数的性质,x和y中只有一个是奇数。证明如下:
先假设x和y都为奇数,那么x = 2m + 1, y = 2n + 1,所以 x^2 + y^2 = (2m+1)^2 + (2n+1)^2 = 4(m^2 + n^2 + m + n) + 2 = 2 (mod 4),所以明显不是平方数。所以x和y中只能有一个奇数。
又z和x,y都互质,且x,y中有一个偶数,那么z必定也是奇数。
欧几里得法则:x = sqrt(mn), y = (m - n)/2, z = (m + n)/2.(其中m、n同奇或者同偶,并且mn是完全平方数)
证明:x^2 = mn , y^2 = (m^2 + 2mn + n^2)/4, z^2 = (m^2 + 2mn + n^2)/4, 易得x^2 + y^2 = z^2,,且按照对m和n的限制,x,y和z均为整数。
丢番图法则: x = m + sqrt(2mn), y = n + sqrt(2mn), z = m + n + sqrt(2mn).(其中2mn为完全平方数)
证明:x^2 = m^2 + 2mn + 2m * sqrt(2mn), y^2 = n^2 + 2mn + 2n * sqrt(2mn), z^2 = m^2 + n ^2 + 4mn + 2(m + n) * sqrt(2mn). 易知 x^2 + y^2 = z^2,且按照对m和n的限制,x,y和z均为整数。
毕达哥拉斯法则: x = 2n + 1, y = 2n^2 + 2n, z = 2n^2+2n+1.(n >= 1)即在一组勾股数中,当最小边为奇数的时候,它的平方正好等于另外两个连续的正整数之和。
证明:x^2 = (2n + 1)^2 = 4n^2 + 4n + 1 = (2n^2 + 2n) + (2n^2 + 2n + 1),易知 (2n + 1)^2 + (2n^2 + 2n)^2 = (2n^2 + 2n + 1)^2
柏拉图法则:x = 2n, y = n^2 - 1, z = n^2 + 1.(n>=2)。即在一组勾股数中,当最小边为偶数的时候,它的平方和刚刚好等于两个连续整数之和的两倍。
证明:(x^2)/2 = 2n^2 = (n^2 - 1) + (n^2 + 1), 易知 (2n)^2 + (n^2 - 1)^2 = (n^2 + 1)^2;
勾股数法则:x = m^2 - n^2, y = 2mn, z = m^2 + n^2.(m>n)
证明:x^2 = m^4 - 2(m^2) * (n^2) + n^4, y^2 = 4(m^2) * (n^2), z^2 =m^4 + 2(m^2) * (n^2) + n^4,易得 x^2 + y^2 = z^2.
顺便提一下勾股数通解公式。取定 x (x>=3)的值后,如果k能使 y = (x^2 - k^2)/2k为整数,z = y + k,
则x,y,z必是勾股数。
这里,使上式中的(x^2-k^2)/2k的值恒为整数的k值条件是:
若x为≥3的奇数,在x^2标准分解因数(包括1)全排列重组乘积中,取小于x的因数积为k。如x=15, 15^2 = 1 * 3^2 * 5^2, k = 1, 3, 5, 3^2.
若x为≥4的偶数,在x^2标准分解因数(包括1)中去掉一个2后为有效因数,在有效因数全排列重组乘积中,
取小于x的偶数因数积为k。 如x=10, 10^2 = 1 * 2^2 * 5^2, k = 2.
勾股数再生公式。a^2 + b^2 = c^2,那么 x = 2(a + c) + b, y = 2(b + c) + a, z = 2(a + b) + 3c, 那么x^2 + y^2 = z^2.
上面的各种法则中,明显是勾股数法则最合适,而且还可以将N从10^6降到10^3,这样想怎样暴力都没问题了。
不过勾股数法则并不能表示所有的勾股数对,例如9, 12, 15 就没办法找出对应的m和n,但是幸好这个特例是
不是互质的,那我们是不是可以勾股数法则可以求出所有的质勾股数,勾股数法会遗漏掉的是m,n为分数的情况
和m,n为无理数的情况,接下来分别讨论这两种情况。
①假设m,n是分数,分别取m/a和n/b (a,b,m,n均为整数, m/a和n/b都是最简分数,且m/a > n/b),所以
x = (m/a)^2 - (n/b)^2, y = 2mn/ab,z =(m/a)^2 + (n/b)^2,所以 x + y = 2(m/a)^2,因为x和y都是整数,
又a^2 != 2,所以2(m/a)^2显然不是整数,所以矛盾了,该假设不成立。
②假设m和n是无理数。分别取m * sqrt(a), n * sqrt(b) (a,b,m,n均为整数, a和b均无法提取出整数 ,
且m * sqrt(a) > n * sqrt(b))。x = (m^2) * a - (n^2) * b, y = 2mnab, z = (m^2) * a + (n^2) * b,
因为y是整数,所以a = b,不然y就不是有理数了。所以x = a * (m^2 - n^y = a * 2mna, z =a * (m^2 + n^2).
显然x,y,z不是互质的。
综上所述,勾股数法则可以求出所有的质勾股数。同时,当我们将质勾股数乘以k倍的时候,
可以得到当m和n是无理数的时候遗漏所有勾股数。
做到这里程序基本就可以过了,但关于m和n的取值还可以进一步优化。当m和n奇偶性相同的时候,所以可以不用考虑。
令gcd(m,n) = d,当d != 1时,x = m^2 - n^2可以整除d^2, y = 2mn可以整除d^2,所以gcd(x,y) = d^2,所以也可以不用考虑。
接下来是代码
#include<cstring>#include<iostream>using namespace std;const int MAXN = 1000 + 5;int cnt;int N, p;int a, b, c;int vis[MAXN * MAXN];int gcd(int x, int y){return y == 0 ? x : gcd(y, x % y);}int main(){cin.sync_with_stdio(false);while(cin >> N){cnt = p = 0;memset(vis, 0, sizeof(vis));for(int n = 1; n * n <= N; ++ n)for(int m = n + 1; (c = n * n + m * m) && c <= N; ++ m)//m和n同奇偶,那么a,b,c都会是偶数if((m & 1) + (n & 1) == 1 && gcd(m, n) == 1){++cnt;b = (m * n) << 1;a = m * m - n * n;for(int k = 1; c * k <= N; ++k)vis[k * a] = vis[k * b] = vis[k * c] = 1;}for(int i = 1; i <= N; ++ i)if(vis[i] == 0)++p;cout << cnt << ' ' << p << endl;}return 0;}
- uva 106 - Fermat vs. Pythagoras(素勾股数)
- UVa 106 - Fermat vs. Pythagoras 素勾股数
- uva 106 - Fermat vs. Pythagoras
- UVA 106 - Fermat vs. Pythagoras
- UVA 106 Fermat vs. Pythagoras
- UVa 106 - Fermat vs. Pythagoras
- UVa 106 - Fermat vs. Pythagoras
- UVA - 106 Fermat vs. Pythagoras
- UVa:106 Fermat vs. Pythagoras
- uva 106 Fermat vs. Pythagoras
- UVA 106 Fermat vs. Pythagoras
- UVa 106 - Fermat vs. Pythagoras
- Uva 106 Fermat vs. Pythagoras
- uva 106 Fermat vs. Pythagoras
- UVA 106 - Fermat vs. Pythagoras (勾股数和素勾股数)
- UVa Problem 106 - Fermat vs. Pythagoras
- UVA 106Fermat vs. Pythagoras(数论)
- Fermat vs. Pythagoras - UVa 106 勾股数
- 看example源码学spark系列(4)-DriverSubmissionTest
- 标签鼠标移动切换标签栏
- Android环境变量的配置
- 三夜频梦君,情亲见君意。
- 多线程-2-线程创建与启动
- UVa 106 - Fermat vs. Pythagoras 素勾股数
- 蜕变
- 抛弃MFC, 转向.Net
- SQL Server判断对象是否存在 (if exists (select * from sysobjects )
- OpenCV2马拉松第26圈——FAST特征点检测
- settimeout(0) 的作用解析
- 机器学习中的算法-Boost算法
- libpoco在mac平台编译详解
- Extjs+PHP 文件下载