UVa 106 - Fermat vs Pythagoras(数论题目)

题目来源:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=42

 Fermat vs. Pythagoras 

Background

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 for n > 2.

The Problem

Given a positive integer N, you are to write a program that computes two quantities regarding the solution of

where xy, 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<yz, and they are relatively prime, i.e., have no common divisor larger than 1. You are also to compute the number of values such that p is not part of any triple (not just relatively prime triples).

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

The 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  ). The second number is the number of positive integers  that are not part of any triple whose components are all  . There should be one output line for each input line.

Sample Input

10
25
100

Sample Output

1 4
4 9
16 27解题思路:

这是一道数论题,用数学的语言描述就是:x, y, z∈N,给定一个数n,找出所有的x, y, z ≤ n,使得x2 + y2 = z2成立。如果要穷举所有的x, y, z的话,按照题目所给的数据量,肯定是无法在限定时间内完成的。考虑利用毕达哥拉斯数的性质生成所有的x, y, z来解决,数学推导简要介绍如下:

先假定x, y, z两两互质,由于x, y互质,故x, y中至少有1个是奇数。下面用反证法证明x和y中有且只有1个奇数。假定x, y都为奇数,设:

  • x = 2a + 1
  • y = 2b + 1
  • x2 + y2 = (2a + 1)2 + (2b + 1)2 
    = 4(a2 + b2 + a + b) + 2

又因为x2和y2是奇数,则z2是偶数,且必能被4整除,与上式矛盾,因此x, y中只有一个奇数。

假设x为奇数,y为偶数,则z为奇数,2z与2x的最大公因数为2,2z和2x可分别写作

  • 2z = (z + x) + (z - x)
  • 2x = (z + x) - (z - x)

那么跟据最大公因数性质,z + x和z - x的最大公因数也为2,又因为:

  • (z + x)(z - x) = y2,两边同除以4得:
    ((z + x) / 2)((z - x) / 2) = (y / 2)2

故可令:

  • z + x = 2m2, z - x = 2n2
    其中z = m + n, x = m - n(m与n互质)

则有:

  • y2 = z2 - x2 = 2m22n2 = 4m2n2
    即y = 2mn。

综上所述,可得到下式:

  • x = m2 - n2, y = 2mn, z = m2 + n2. (m, n为任意自然数)

这里还有一个问题:题目要求统计(x, y, z)三元组的数量时只统计x,y和z两两互质的的情况,这个问题用上面的算法就可以解决了。但对于统计p的数量,题目并不限定三元组是两两互质的。但是上式不能生成所有x, y, z并不是两两互质的情况。然而假设x与y最大公因数w不为1,则z也必能被w整除,因此w为x, y, z三个数的公因数。归纳总结可知,所有非两两互质的x0, y0, z0都可由一组互质的x, y, z乘以系数得到。根据以上理论就可以快速的求解了。


参考代码:
 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstring>
 4 #define N 1000010
 5 bool used[N];
 6
 7 long long gcd(long long a , long long b)
 8 { return b==0 ? a: gcd(b,a%b); }
 9
10 int main()
11 {
12     long long n,a,b,c;
13     long long count1,count2;
14     while(scanf("%lld",&n)!=EOF)
15     {
16         count1=count2=0;
17         memset(used,0,sizeof(used));
18         long long m=(long long)sqrt(n+0.5);
19         for(long long t=1; t<=m; t+=2)
20             for(long long s=t+2; s*t<=n; s+=2)
21                 if(gcd(s,t)==1)  //s>t>=1且s与t互质
22                 {
23                     a=s*t;          //奇数
24                     b=(s*s-t*t)/2;  //偶数
25                     c=(s*s+t*t)/2;  //奇数
26                     if(c<=n)        //在n范围内的PPT
27                     {
28                         count1++;
29                         //printf("本原勾股数组:%lld %lld %lld\n",a,b,c);
30                         if(!used[a]) { count2++; used[a]=1; }
31                         if(!used[b]) { count2++; used[b]=1; }
32                         if(!used[c]) { count2++; used[c]=1; }
33
34                         for(int j=2; c*j<=n; j++)  //j是倍数
35                         {
36                             if(!used[a*j]) { count2++; used[a*j]=1; }
37                             if(!used[b*j]) { count2++; used[b*j]=1; }
38                             if(!used[c*j]) { count2++; used[c*j]=1; }
39                         }
40                     }
41                 }
42             printf("%lld %lld\n",count1,n-count2);
43     }
44     return 0;
45 }
时间: 2024-08-04 16:39:01

UVa 106 - Fermat vs Pythagoras(数论题目)的相关文章

UVa 106 - Fermat vs. Pythagoras

题目:找到小于N的勾股数组的朴素解(三个数互质),并找到[1, N]中所有勾股数组中未出现过的数字个数. 分析:数论.这里直接利用<原本>中的解法即可. x = 2st,y = s^2 - t^2,z = s^2 + t^2, 其中:1.s > t:(枚举顺序) 2.s和t互质:(朴素解) 3.s和t奇偶性不同:(反证法证明) 在计算未出现的数字时,需要枚举朴素解的倍数. 说明:伟大的欧几里得╮(╯▽╰)╭. #include <cstring> #include <c

数论(毕达哥拉斯定理):POJ 1305 Fermat vs. Pythagoras

Fermat vs. Pythagoras Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 1493   Accepted: 865 Description Computer generated and assisted proofs and verification occupy a small niche in the realm of Computer Science. The first proof of the

UVA 1341 - Different Digits(数论)

UVA 1341 - Different Digits 题目链接 题意:给定一个正整数n,求一个kn使得kn上用的数字最少,如果相同,则输出值最小的 思路: 首先利用鸽笼原理证明最多需要2个数字去组成 设一个数字k,组成k,kk,kkk,kkkk... %n之后余数必然在0 - (n - 1)之间,所以必然能选出两个余数相等的数字相减为0,这个数字就是由0和k组成的. 因此只要考虑一个数字和两个数字的情况,去bfs,记忆化余数,因为余数重复必然形成周期了 代码: #include <stdio.

UVA 10693 10693 - Traffic Volume(数论)

题目链接:10693 - Traffic Volume 根据物理知识, 车经过的时间等于,距离/速度,所以可以列出公式t = (l + d)/v,v/2f + d/v,只有当v / 2f = d/v时,时间最小,v = sqrt(2df),之后时间也能算了. #include <stdio.h> #include <string.h> #include <math.h> double l, f; int main() { while (~scanf("%lf%

UVA 618 - Doing Windows(数论)

题目链接:618 - Doing Windows 题意:给定一个大小不能变的屏幕,和四个大小可以变的窗口,变化要保持长宽比,问这四个窗口能不能调整后全部放下正好填满屏幕,不能重叠 思路:情况一共就几种:4个叠一起,3个叠一起+一个,2个和2个,一个和两个叠一起在一个,把这几种情况全判断了就可以了,判断过程利用gcd,lcm可以求边长. 代码: #include <stdio.h> #include <string.h> long long gcd(long long a, long

UVA 1426 - Discrete Square Roots(数论)

UVA 1426 - Discrete Square Roots 题目链接 题意:给定X, N, R,要求r2≡x (mod n) (1 <= r < n)的所有解,R为一个已知解 思路: r2≡x (mod n)=>r2+k1n=x 已知一个r!,带入两式相减得 r2?r12=kn => (r+r1)(r?r1)=kn 枚举A,B,使得 A * B = n (r + r1)为A倍数 (r - r1)为B倍数 这样就可以推出 Aka?r1=Bkb+r1=r => Aka=Bk

uva 10515 - Powers Et Al.(数论)

题目链接:uva 10515 - Powers Et Al. 题目大意:给出m和n,问说mn的个数上的数是多少. 解题思路:其实只要看m的最后一位数就可以了,判断最有一位的周期,然后用n%t即可. #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 15; const int maxs = 105; vector<int> g

UVA 11490 - Just Another Problem(数论)

11490 - Just Another Problem 题目链接 题意:有S个士兵,排成一个矩阵,矩阵中可以有两个洞,要求两个洞上下左右厚度一样,问能缺少士兵的情况数. 思路:推推公式,设厚度为a, 正方形为i, 那么(3 a + 2 i) (2 a + i) = S + 2 i i; 化简一下得到6 i i + 7 a i = S 由于S很大,所以去枚举厚度,这样只要枚举到sqrt(S)就够了,复杂度可以接受 代码: #include <stdio.h> #include <stri

UVA 417 - Word Index(数论)

题意:417 - Word Index 题意:每个字符串按题目中那样去映射成一个数字,输入字符串,输出数字 思路:这题还是比较水的,由于一共只有83000多个数字,所以对应一个个数字去映射就可以了,注意字符串进位的情况处理即可 代码: #include <stdio.h> #include <string.h> #include <map> #include <string> using namespace std; char str[10]; map<