poj2407欧拉函数模板

第一次接触欧拉函数,phi(x)为小于等于x且与x互质的数的个数……先介绍一些基本定理

1.定义在所有正整数上的函数成为算数函数。

2.一个算术函数f,如果对于两个互素整数m,n有f(nm)=f(n)*f(m)则称f为积性函数。如果对于任意两个正整数mn有f(nm)=f(n)*f(m)则称f为完全积性函数。

3.如果f是一个积性函数,则对于正整数n=p1^a1*p2^a2……(pi为素数),则f(n)=f(p1^a1)*f(p2^a2)……

4.若p为素数,则phi(p)=p-1.同时,若phi(p)=p-1,则p为素数

5若p为素数,则phi(p^a)=p^a-p^(a-1),简单证明:p^a只有p的倍数的因子为p^(a-1)个。

6.n=p1^a1*p2^a2……则phi(n)=n*(1-1/p1)*(1-1/p2)……该式可由5推出

7.当n为奇数时,有phi(2n)=phi(n)。

8.设n为一大于2的正整数,则phi(n)为偶数


介绍几种求欧拉函数的方法

(1)直接求解,从1遍历到根号n,找出素因子,套入公式,接着将该素因子全部除去,最后判断n是否本身就是素数。

(2)筛法求出素数表,除去筛的时间,其复杂度变为o(x),x为小于n的素数个数

(3)递推求欧拉函数,适合于多次运用事先打表的情况,复杂度为o(nlnn)

算法原理:开始令i的欧拉函数值等于它本身,如果i为偶数,可以利用定理二变为求奇数的。

若p是一个正整数满足,那么p是素数,在遍历过程中如果遇到欧拉函数值等于自身的情况,那么

说明该数为素数。把这个数的欧拉函数值改变,同时也把能被该素因子整除的数改变。

代码

void phi()  
{  
    for(int i=1; i<N; i++)  p[i] = i;  
    for(int i=2; i<N; i+=2) p[i] >>= 1;  
    for(int i=3; i<N; i+=2)  
    {  
        if(p[i] == i)  
        {  
            for(int j=i; j<N; j+=i)  
                p[j] = p[j] - p[j] / i;  
        }  
    }  
}  



poj 2407

Relatives
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 13014   Accepted: 6439

Description

Given n, a positive integer, how many positive integers less than n are relatively prime to n? Two integers a and b are relatively prime if there are no integers x > 1, y > 0, z > 0 such that a = xy and b = xz.

Input

There are several test cases. For each test case, standard input contains a line with n <= 1,000,000,000. A line containing 0 follows the last case.

Output

For each test case there should be single line of output answering the question posed above.

Sample Input

7
12
0

Sample Output

6
4


思路:裸的欧拉函数


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <functional>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

long long phi(long long n)
{   
	long long  i,cnt,j;
	cnt=n;
	for(i=2;i*i<=n;i++)
	{
	  if(n%i==0)
	  {
	  	cnt=cnt-cnt/i;
	  	while(n%i==0)n=n/i;
	  }
	}
	if(n>1)cnt=cnt-cnt/n;
    return cnt;
	
}

int main(int argc, char const *argv[])
{
	long long i,j,k,m,n;
	while(~scanf("%lld",&n))
	{
		if(n==0)break;
		printf("%lld\n",phi(n));
	}
	return 0;
}





你可能感兴趣的:(ACM,poj,欧拉函数)