Farey Sequence
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 15235 | Accepted: 6051 |
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 <= 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
Source
POJ Contest,Author:Mathematica@ZSU
题意:该题可以转化成欧拉函数的连续值。
分析:如果每次调用欧拉函数肯定会超时,可以转化成一个思路。在此代码借鉴了网上的代码,有详细的备注。代码主要运用了欧拉函数的一些性质进行优化。欧拉函数性质参见:http://blog.youkuaiyun.com/qq_26071477/article/details/52356066 见代码:
//求取大范围的连续整数的欧拉函数值 使用 避免每次调用欧拉函数重复调用
//普通求取欧拉函数的求法 在于求取每个数都调用了欧拉函数
//改进后的算法在于 保留了过程 在前面计算的基础上求出后面的值
#include <stdio.h>
const int maxn=1000005 ;
int phi[maxn],prime[100000];//phi 表示欧拉函数值
bool unprime[maxn];
long long sum[maxn];
void euler()
{
int k;
for(int i=2,k=0; i<maxn; i++)
{
if(!unprime[i])// 是质数的话
{
// printf("%d ",i);
prime[k++]=i; //质数数组添加一个质数
phi[i]=i-1;//质数的欧拉函数值 是i-1
}
for(int j=0; j<k&&prime[j]*i<maxn; j++)//j表示的是质数数组的下标
{
//任何非负整数都存在质因子 任何整数都是一个质数或者非质数 乘以一个质因子得到 例如8 = 4*2
//这里即可将所有非质数标记为真 质因子判断法
//求出的素数和每个已求得的素数相乘得到非素数的欧拉函数值 充分利用此性质
//素数本身的欧拉函数值可以直接减一得到
unprime[prime[j]*i]=true; //质数和质数相乘得到的数 不再是质数
/*在这里需要利用两个性质。第一,大于1的质数x的欧拉函数值为x-1,1的欧拉函数值为1。
第二,若a为N的质因数,若(N % a == 0 && (N / a) % a == 0) 则有E(N)=E(N / a) * a;
若(N % a == 0 && (N / a) % a != 0) 则有:E(N) = E(N / a) * (a - 1)。*/
if(i%prime[j]) //根据欧拉函数性质
phi[prime[j]*i]=phi[i]*(prime[j]-1);
else
{
phi[prime[j]*i]=phi[i]*prime[j];
break;//再扩大则是上述情况 此情况是指数较小的情况
}
}
}
}
int main()
{
int n;
euler();
for(int i=1; i<maxn; i++)
sum[i]=sum[i-1]+phi[i];
while(scanf("%d",&n)&&n)
printf("%lld\n",sum[n]);
}
刷题长见识……
特记下,以备后日回顾。