POJ 2478 Farey Sequence 欧拉函数

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.

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]);
}

    刷题长见识……

    特记下,以备后日回顾。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值