第一次接触欧拉函数,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
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 13014 | Accepted: 6439 |
Description
Input
Output
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; }