poj2478——Farey Sequence(欧拉函数)
Farey Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 18507 | Accepted: 7429 |
Description
The Farey Sequence Fn for any integer n with n >= 2 is the set of irreducible rational numbers a/b with 0 < a < b <= n and gcd(a,b) = 1 arranged in increasing order. The first few are
F2 = {1/2}
F3 = {1/3, 1/2, 2/3}
F4 = {1/4, 1/3, 1/2, 2/3, 3/4}
F5 = {1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5}
You task is to calculate the number of terms in the Farey sequence Fn.
F2 = {1/2}
F3 = {1/3, 1/2, 2/3}
F4 = {1/4, 1/3, 1/2, 2/3, 3/4}
F5 = {1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5}
You task is to calculate the number of terms in the Farey sequence Fn.
Input
There are several test cases. Each test case has only one line, which contains a positive integer n (2 <= n <= 106). There are no blank lines between cases. A line with a single 0 terminates the input.
Output
For each test case, you should output one line, which contains N(n) ---- the number of terms in the Farey sequence Fn.
Sample Input
2 3 4 5 0
Sample Output
1 3 5 9
题意:给出一个数n,要你求出在1-n中,互质的数有多少对;
思路:这题属于欧拉函数的应用。1-n中互质数的对数就是等于与2互质的数的个数+与3互质的数的个数+与4互质的数的个数+....+与n互质的数的个数。(为什么没有1,因为一个数无法成对)
所以这题就演变成了求2-n中所有数的欧拉函数的和,所以要用到欧拉函数的变形写法。
因为是多组输入,所以要预处理一下,提前记录下n为1-1000000时的值。
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<string> 5 #include<cmath> 6 #include<algorithm> 7 #include<stack> 8 #include<queue> 9 #define eps 1e-7 10 #define ll long long 11 #define inf 0x3f3f3f3f 12 #define pi 3.141592653589793238462643383279 13 using namespace std; 14 ll n,euler[1000006],sum[1000006]; 15 int main() 16 { 17 for(int i=1; i<=1000000; ++i) //初始化所有数的欧拉函数值为自己 18 euler[i] = i; 19 for(int i=2; i<=1000000; ++i) //求所有数的欧拉函数值 20 { 21 if(euler[i] == i) //根据公式 欧拉值(n) = n*(1-1/p1)(1-1/p2)...(1-1/pi)其中p为n的素因子 22 //可知素数只有自己是自己的素因子,所以在遇到自己以前euler值没变,所以可以通过上面的语句得知euler[i]==i的为素数 23 { 24 for(int j=i; j<=1000000; j+=i) //所有i的倍数乘上(1-1/i) 25 euler[j] = euler[j]/i*(i-1); 26 } 27 } 28 sum[1] = 0; 29 for(int i=2; i<=1000000; ++i) //提前记录下每个数的答案 30 { 31 sum[i] = sum[i-1] + euler[i]; 32 } 33 while(scanf("%lld",&n)!=EOF) 34 { 35 if(!n) break; 36 printf("%lld\n",sum[n]); 37 } 38 return 0; 39 }