• 欧拉函数模板


    定义:欧拉函数是指小于x的数中,与x互质的数的个数。

    特别的,我们知道1的欧拉函数值为0,素数p的欧拉函数值为p-1,当数x不是p素数时,由唯一分解定理我们知道x=p1a1*p2a2*p3a3*……*pnan,其中p1,p2……pn皆为素数,则:phi[x]=x*(p1-1)/p1*(p2-1)/p2……*(pn-1)/pn,证明略。由此我们可以得到一个非线性的求欧拉函数的算法。

    void euler() {
       phi[1]=0;
        for(int i=2;i<maxn;i++)
        {
            if(!phi[i])//素数 
                for(int j=i;j<maxn;j+=i)//素数去筛它所有的倍数 
    	   {
                    if(!phi[j])phi[j]=j;//初始值 
                    phi[j]=phi[j]/i*(i-1);//公式 
                }
        }
    }
    

      其实欧拉函数还有线性的求法,这里我们需要知道:

    1:phi[pk]=pk-pk-1,因为与pk不互质的数有p,2p,3p……(pk-1-1)*p,所以phi[pk]=pk-1-(pk-1-1)=pk-pk-1

    2:如果i是p的倍数,那么phi[i*p]=p&phi[i],否则phi[i*p]=(p-1)*phi[i].

    这样我们就可以在进行素数筛的时候顺便把欧拉函数求出来。

    void getphi(int n)
    {
    	vis[0]=vis[1]=1,phi[1]=0;
    	for(int i=2;i<=n;++i)
    	{
    		if(!vis[i])
    		{
    			pri[++cnt]=i,phi[i]=i-1;
    		}
    		for(int j=1;j<=cnt&&pri[j]*i<=n;++j)
    		{
    			vis[i*pri[j]]=1;
    			if(i%pri[j]==0)
    			{
    				phi[i*pri[j]]=pri[j]*phi[i];
    				break;
    			}else
    			phi[i*pri[j]]=(pri[j]-1)*phi[i];
    		}
    	} 
    }
    

      当然,如果我们只需要求一个数的欧拉函数值,就不用这么麻烦了,直接枚举它的因子,按照公式计算就可以了。

    for(int i=2;i<=n;++i)
    	{
    		if(n%i==0)ans=ans/i*(i-1);//因为是从小到大枚举的因子,所以一定都是素因子,这个复杂度比线性的未必小多少,
    //但是如果不需要打表的时候写着省事,而且节省空间 while(n%i==0)n/=i; }

      

  • 相关阅读:
    在OpenEuler中安装轻量化调试工具CGDB
    nginx服务器 server location映射路径配置
    hadoop HDFS文件系统角色及文件读写流程
    Linux系统Tomcat服务自启动脚本
    Linux系统软件安装的三种方式
    linux基础命令
    Java多线程解析
    多线程的典型应用场景---多个生产者多个消费者对共享资源的处理
    10.16变量的作用域和生存周期
    10.15sizeof用法
  • 原文地址:https://www.cnblogs.com/yuelian/p/12652024.html
Copyright © 2020-2023  润新知