一、题目
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 <= 10 6). 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的数字去组合成Farey序列。关于Farey序列,依题意可知,就是1~N的数字中互素的a,b,其中a<b,就可以凑成一个a/b。然后问有多少个不同的a/b。
我们先看2,就一个,看3,发现2有的3肯定有,然后其余的就是与3互质的数与3凑成的a/b。再看4,3有的还是有,然后再加上与4互质的数与4凑成的a/b。依次递推下去。就是欧拉函数的前N项和。用一个数组累加保存下来,就是所有结果了,再用线性筛法去求欧拉函数(可以看我之前的欧拉函数学习笔记),速度绝对够。需要注意的是,结果增长的很快,需要用long long。
三、AC代码
#include <iostream> #include <cstring> using namespace std; const int MAXN = 1e6+5; int Phi[MAXN], Prime[MAXN], nPrime; long long Ans[MAXN]; void Euler() { memset(Phi, 0, sizeof(Phi)); Phi[1] = 1; nPrime = 0; for(int i = 2; i < MAXN; i++) { if(!Phi[i]) //i为素数 { Phi[i] = i - 1; Prime[nPrime++] = i; } for(int j = 0; j < nPrime && (long long)i*Prime[j] < MAXN; j++) { if(i%Prime[j]) { Phi[ i*Prime[j] ] = Phi[i]*(Prime[j]-1); } else { Phi[ i*Prime[j] ] = Phi[i]*Prime[j]; break; } } } return; } void solve() { Euler(); Ans[2] = Phi[2]; for(int i = 3; i < MAXN; i++) { Ans[i] = Ans[i-1] + Phi[i]; } return; } int main() { int N; solve(); while(cin>>N && N) { cout << Ans[N] << endl; } return 0; }