菜鸡学习数论第三天 之 欧拉函数

质因子
  质因子(质因数)是指能整除给定正整数的质数。比如说6,它的质因子是2和3。(6= 2 * 3)
  质因子与因子的区别:质因子是需要能够整除给定的正整数同时它是质数。因子只要是整除给定的数,就是因子不需要是质数。

欧拉函数
  1~N中与N互质的数的个数被称为欧拉函数,记为Φ(N).
  Φ(N)=N*(p1-1)/p1*(p2-1)/p2*……(pm-1)/pm;(其中p1,p2……pm为N的所有质因数)
     =N*(Π(1-1/p))(累乘条件(质数p|N));(|是整除符号)

证明:1).假设p是N的质因子,那么1~N中所含p的倍数有p,2p,3p,4p……[N/p] * p,一共有[N / p]个。
   2).同理,假设q也是N的质因子,那么1~N中所含q的倍数有N/q个。
   3).我们将p与q在1~N中的倍数所去掉,但是去掉的数当中可能含有同时是q和p倍数的数,换句话说可能有些数去掉了两次。所以,我们还需要将这些重复去掉的数给它加起来,重复去掉的数的个数为(N/p/q)。
   综上3点,我们可知1~N中不与N有共同质因子p或q的数的个数为: N - N / p - N / q+N / ( p * q)=N * (1-1/p-1/q+1/p/q)=N/(1-1/p)(1-1/q);(容斥原理)
那么我们可以得到1~N中不与N含有任何共同质因子的数的个数,也就是与N互质的个数。即为Φ(N)=N*(Π(1-1/p))(累乘条件(质数p|N));(|是整除符号)
  代码如下:

int phi(int n){
    int ans=n;
    for(int i=2;i<=sqrt(n);i++){
        if(n%i==0){
            ans=ans/i*(i-1);//相当于上面证明的第一步
            while(n%i==0)n/=i;//把i这个质因数去掉 即这一步之后的n与现在的i互质 
                              //防止重复计数
        }
    }
    if(n>1)ans=ans/n*(n-1);//如果不等于1的话,最后还剩下一个质因数,
                           //将最后的质因数也进行相同操作
    return ans;
}

接下来是欧拉函数打表的代码:

int euler(){
    for(int i=2;i<=n;i++){
        phi[i]=i;
    }
    for(int i=2;i<=n;i++){
        if(phi[i]==i){
            for(int j=1;j<=n;j+=i)
               phi[j]=phi[j]/i*(i-1);
        }
    }
}

欧拉函数未优化的复杂度为O(N log N).

上面代码可以优化,变成复杂度为O(N)的

代码如下:

int v[maxn],prime[maxn],phi[maxn];
void euler(int n){
    memset(v,0,sizeof v);
    m=0;
    for(int i=2;i<=n;i++){
        if(v[i]==0){
            v[i]=i,prime[++m]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=m;j++){
            if(prime[j]>v[i]||prime[j]>n/i)break;
            v[i*prime[j]]=prime[j];
            phi[i*prime[j]]=
                phi[i]*(i%prime[j]?prime[j]-1:prime[j]);
        }
    }
}

这个优化是用到线性筛的思想实现的。

欧拉函数的一些性质

1).对于任意的n>1,1~n中与n互质的数的和为n*Φ(n)/2;
2).若a,b互质,则Φ(ab)=Φ(a)Φ(b)

证明:

因为gcd(n,x)=gcd(n,n-x),所以与n不互质的数x,n-x成对出现,平均值为n/2,因此与n互质的数的平均数也是n/2,进而得出性质1;
根据欧拉函数的计算式,对a,b分解质因数,直接可得性质2.把性质2推广到一般函数上,可以得到“积性函数”的性质

参考:李煜东《算法竞赛进阶指南》
非常感谢苏学长的帮助

道阻且长
自己选的路 跪着也要走完。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值