• 欧拉函数模板及拓展


    在数论,对正整数n,欧拉函数是 小于 n的正整数中与n互质的数的数目(φ(1)=1)。此函数以其首名研究者欧拉命名(Euler’s totient function),它又称为Euler’s totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质。
    其中1的欧拉函数φ(1)=1

    欧拉公式的延伸:对于一个数,与其互质的数的总和是euler(n)n/2。
    如φ(15)=8,有互质数 1,2,4,7,8,11,13,14,加和后结果为60,而8
    15/2结果同为60。
    通常用phi表示欧拉函数或存储欧拉函数的数组

    特性 :
    1.若a为质数,phi[a]=a-1;
    2.若a为质数,b mod a=0,phi[a * b]=phi[b] * a【 b是 质数a 的倍数则ab的欧拉函数是b的欧拉函数的a倍 φ(a * b)=φ(b) * a】
    3.若a,b互质,phi[a * b]=phi[a] * phi[b]【当a为质数时,if (b mod a)!=0 ,phi[a
    b]=phi[a] * phi[b]】
    4.特殊性质:当n为奇数时,φ(2*n)=φ(n)

    *φ(1) = 1
    *φ(2) = 1
    *φ(3) = 2
    *φ(4) = 2
    φ(5) = 4
    *φ(6) = 2
    φ(7) = 6
    φ(8) = 4
    φ(9) = 6
    φ(10) = 4
    φ(11) = 10
    φ(12) = 4
    φ(13) = 12
    φ(14) = 6
    φ(15) = 8
    φ(16) = 8
    φ(17) = 16
    φ(18) = 6
    φ(19) = 18
    φ(20) = 8
    φ(21) = 12
    φ(22) = 10
    φ(23) = 22
    φ(24) = 8
    φ(25) = 20
    φ(26) = 12
    φ(27) = 18
    φ(28) = 12
    φ(29) = 28
    φ(30) = 8
    φ(31) = 30
    φ(32) = 16
    φ(33) = 20
    φ(34) = 16
    φ(35) = 24
    φ(36) = 12
    φ(37) = 36
    φ(38) = 18
    φ(39) = 24
    φ(40) = 16
    φ(41) = 40
    φ(42) = 12
    φ(43) = 42
    φ(44) = 20
    φ(45) = 24
    φ(46) = 22
    φ(47) = 46
    φ(48) = 16
    φ(49) = 42
    φ(50) = 20

    可以发现只有φ(1),φ(2),φ(3),φ(4),φ(6)是质数,其余所有欧拉函数都是合数。

    Euler函数表达通式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数。

    log(n)单个数字求解欧拉函数模板:

    int phi(int n)
    {
        int ans=n,tmp=n;
        for(int i=2; i*i<=tmp; i++)     ///遍历所有质因子,其中tmp遍历范围因为去除了质因子的倍数一直在变小
        {
            if(tmp%i==0)
            {
                ans=ans/i*(i-1);        ///此处是x*(1-1/p1)=x*(p1-1)/p1,为防止溢出,先计算除法
                while(tmp%i==0)tmp/=i;  ///去除质因子倍数
            }
        }
        if(tmp>1)ans=ans/tmp*(tmp-1);
        return ans;
    }
    

    nlog(n)打表欧拉函数:

    const int MAXN=100005;
    int euler[MAXN];
    void Init()
    {
        euler[1]=1;
        for(int i=2;i<MAXN;i++) euler[i]=i;
        for(int i=2;i<MAXN;i++)
        {
            if(euler[i]==i)
            {
                for(int j=i;j<MAXN;j+=i)
                {
                    euler[j]=euler[j]/i*(i-1);
                }
            }
        }
        for(int i=1;i<=50;i++)printf("φ(%d) = %d
    ",i,euler[i]);
    }
    

    O(n)线性筛打表欧拉函数(1s内可以打表2e7的欧拉函数):

    LL euler[maxn]={0};///欧拉函数
    LL prime[maxn],cnt=0;///素数
    bool vis[maxn];
    void Init()///线性欧拉筛
    {
        euler[1]=1;
        memset(vis,false,sizeof vis);
        for(int i=2;i<maxn;i++)
        {
            if(!vis[i])prime[++cnt]=i,euler[i]=i-1;///素数情况
            for(int j=1;j<=cnt&&i*prime[j]<=maxn;j++)
            {
                vis[i*prime[j]]=1;///素数倍数非素数
                if(i%prime[j])euler[i*prime[j]]=euler[i]*(prime[j]-1);
                else
                {
                    euler[i*prime[j]]=euler[i]*prime[j];
                    break;
                }
            }
    //        printf("φ(%d)=%lld
    ",i,euler[i]);
        }
    }
    
  • 相关阅读:
    学期总结
    C语言I博客作业09
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言II—作业04
    C语言II—作业03
    C语言II—作业02
    C语言II博客作业01
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135738.html
Copyright © 2020-2023  润新知