Skip to content

欧拉函数总结

介绍

欧拉函数的定义:对于正整数n,欧拉函数是小于等于n的数中,与n互质的数的数目

欧拉函数又称ϕ函数,例如ϕ(8)=4,因为1,3,5,7均和8互质

定理:

  1. 如果n为某一个素数p,则:ϕ(p)=p1
  2. 如果n为某一个素数p的幂次pa,则:ϕ(pa)=(p1)pa1
  3. 如果n为任意两个互质的数a,b的乘积,则:ϕ(ab)=ϕ(a)ϕ(b)
  4. n=p1a1p2a2...pkak为正整数n素数幂分解,那么ϕ(n)=n(11p1)(11p2)...(11pk)推论: 当n为奇数时,有ϕ(2n)=ϕ(n)

以下是两个常用的定理:

  • 欧拉定理:对于正整数a,mm2)且 am 互质(gcd(a,m)=1),有aϕ(m)1(modm)
  • 费马小定理: 当m是质数且ma(即gcd(a,m)=1)时,am11(modm)

模板

返回小于等于n且与n互质的数的个数

cpp
int euler_phi(int n)  
{  
    int res = n;  
    int m = (int)sqrt(n);  
    for(int i = 2; i <= m; i++)  
        if(n % i == 0)  
        {  
            res = res / i * (i-1);  
            while(n % i == 0) n /= i;  
        }  
    if(n > 1) res = res / n * (n-1);  
    return res;  
}

时间复杂度 O(n)

筛选法求欧拉函数(比较慢)

cpp
void euler_phi()  
{  
    for(int i = 1; i < N; i++) phi[i] = i;  
    for(int i = 2; i < N; i++)  
        if(phi[i] == i) //成立说明i是素数
            for(int j = i; j < N; j += i) //j要从i开始,这样可以处理素数的情况  
                phi[j] = phi[j] / i * (i-1);  
}

时间复杂度 O(NloglogN)

线性筛法求欧拉函数:

cpp
int phi[N+10],prime[N+10],tot,ans;
bool mark[N+10];
void getphi()
{
    int i,j;
    phi[1]=1;
    for(i=2; i<=N; i++) //相当于分解质因式的逆过程
    {
        if(!mark[i])
        {
            prime[++tot]=i;//筛素数的时候首先会判断i是否是素数。
            phi[i]=i-1;//当 i 是素数时 phi[i]=i-1
        }
        for(j=1; j<=tot; j++)
        {
            if(i*prime[j]>N)  break;
            mark[i*prime[j]]=1;//确定i*prime[j]不是素数
            if(i%prime[j]==0)//接着我们会看prime[j]是否是i的约数
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else  phi[i*prime[j]]=phi[i]*(prime[j]-1);//其实这里prime[j]-1就是phi[prime[j]],利用了欧拉函数的积性
        }
    }
}

时间复杂度 O(N)

基于 MIT 协议发布 · 使用 VitePress 构建