zoukankan      html  css  js  c++  java
  • 欧拉函数学习笔记

    原理

    请思考以下问题:

    任意给定正整数n,请问在小于等于n的正整数之中,有多少个与n构成互质关系?(比如,在1到8之中,有多少个数与8构成互质关系?)

    计算这个值的方法就叫做欧拉函数,以φ(n)表示。在1到8之中,与8形成互质关系的是1、3、5、7,所以 φ(n) = 4。

    φ(n) 的计算方法并不复杂,但是为了得到最后那个公式,需要一步步讨论。

    第一种情况

    如果n=1,则 φ(1) = 1 。因为1与任何数(包括自身)都构成互质关系。

    第二种情况

    如果n是质数,则 φ(n)=n-1 。因为质数与小于它的每一个数,都构成互质关系。比如5与1、2、3、4都构成互质关系。

    第三种情况

    如果n是质数的某一个次方,即 n = p^k (p为质数,k为大于等于1的整数),则

    (phileft(p^{k} ight)=p^{k-p^{k-1}})

    比如 φ(8) = φ(2^3) =2^3 - 2^2 = 8 -4 = 4。

    这是因为只有当一个数不包含质数p,才可能与n互质。而包含质数p的数一共有p(k-1)个,即1×p、2×p、3×p、...、p(k-1)×p,把它们去除,剩下的就是与n互质的数。

    上面的式子还可以写成下面的形式:

    (phileft(p^{k} ight)=p^{k-p k-1}=p^{k}left(1-frac{1}{p} ight))

    可以看出,上面的第二种情况是 k=1 时的特例。

    第四种情况

    如果n可以分解成两个互质的整数之积,

    n = p1 × p2

    φ(n) = φ(p1p2) = φ(p1)φ(p2)

    即积的欧拉函数等于各个因子的欧拉函数之积。比如,φ(56)=φ(8×7)=φ(8)×φ(7)=4×6=24。

    这一条的证明要用到"中国剩余定理",这里就不展开了,只简单说一下思路:如果a与p1互质(a<p1),b与p2互质(b<p2),c与p1p2互质(c<p1p2),则c与数对 (a,b) 是一一对应关系。由于a的值有φ(p1)种可能,b的值有φ(p2)种可能,则数对 (a,b) 有φ(p1)φ(p2)种可能,而c的值有φ(p1p2)种可能,所以φ(p1p2)就等于φ(p1)φ(p2)。

    第五种情况

    因为任意一个大于1的正整数,都可以写成一系列质数的积。
    (n=p_{1}^{k_{1}} p_{2}^{k_{2} ldots p_{r} r})

    根据第4条的结论,得到
    (phi(n)=phileft(p_{1}^{left.k_{1} ight)} phileft(p_{2}^{k_{2}} ight) ldots phileft(p_{r r}^{k_{r}} ight) ight.)

    再根据第3条的结论,得到

    (phi(n)=p_{1}^{k_{1}} p_{2}^{k_{2}} ldots p_{r}^{k_{r}} left(1-frac{1}{p_{1}} ight)left(1-frac{1}{p_{2}} ight) ldotsleft(1-frac{1}{p_{r}} ight))

    也就等于

    (phi(n)=nleft(1-frac{1}{p_{1}} ight)left(1-frac{1}{p_{2}} ight) ldotsleft(1-frac{1}{p_{r}} ight))

    这就是欧拉函数的通用计算公式。比如,1323的欧拉函数,计算过程如下:

    (phi(1323)=phileft(3^{3} imes 7^{2} ight)=1323left(1-frac{1}{3} ight)left(1-frac{1}{7} ight)=756)

    性质

    (1)对于质数(n,φ(n)=n−1)

    (2)对于(n=p^k,φ(n)=(p−1)∗p^{k−1})

    (3)对于 (n=prod p_{i}^{k_{i}})(varphi(n)=n * prodleft(1-frac{1}{p_{i}} ight))

    (4) 对于(gcd(n,m)=1)(varphi(n * m)=varphi(n) * varphi(m))

    (5) 【欧拉定理】 对于互质的(a,m)(a^{varphi(m)} equiv 1 quad(mod m))

    (6) 小于n且与n互质的数的和:(S=n * frac{varphi(n)}{2})

    (7) 对于质数p

    (n quad mod p=0), $ φ(n∗p)=φ(n)∗p$,

    (n quad mod p eq 0)(varphi(n * p)=varphi(n) *(p-1))

    (8)(sum_{d mid n} varphi(d)=n)

    (varphi(n)=sum_{d mid n} mu(d) * frac{n}{d})

    (9)【欧拉降幂公式】

    (a^{b} equivleft{egin{array}{ll}a^{b \% phi(p)} & g c d(a, p)=1 \ a^{b} & g c d(a, p) eq 1, b<phi(p) \ a^{b \% phi(p)+phi(p)} & g c d(a, p) eq 1, b geq phi(p)end{array} quad(mod p) ight.)

    模板

    直接质因数分解法

    //POJ 2407,给定n,求小于n且和n互质的数个数
    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const ll maxn=1e5+5;
    const ll maxp=1e5+5;
    bool isPrime[maxn];
    ll Prime[maxp], primecnt = 0;
    void GetPrime(ll n){//筛到n
    	memset(isPrime, 1, sizeof(isPrime));
    	isPrime[1] = 0;//1不是素数
    	for(ll i = 2; i <= n; i++){
    		if(isPrime[i])//没筛掉
    			Prime[++primecnt] = i; //i成为下一个素数
    		for(ll j = 1; j <= primecnt && i*Prime[j] <= n; j++) {
    			isPrime[i*Prime[j]] = 0;
    			if(i % Prime[j] == 0)//i中也含有Prime[j]这个因子
    				break;
    		}
    	}
    }
    ll getol(ll n){
        if(n==0){
            return 0;
        }
        ll ans=n;
        ll temp=n;
        for(ll i=1;i<=primecnt;i++){
            if(temp%Prime[i]==0){
                ans=ans*(Prime[i]-1)/Prime[i];
                while(temp%Prime[i]==0)
                    temp/=Prime[i];
            }
            if(temp<Prime[i]*Prime[i]){
                break;
            }
        }
        if(temp>1){
            ans=ans*(temp-1)/temp;
        }
        return ans;
    }
    int main () {
        GetPrime(maxn-5);
        ll n;
        while(~scanf("%lld",&n)){
            if(n==0){
                break;
            }
            ll ans=getol(n);
            printf("%lld
    ",ans);
        }
    }
    

    线性素数筛法

    原理:

    • 若i%p=0,p是素数,那么(φ(i*p)=φ(i)*p)
    • 若i%p!=0,p是素数,那么(φ(i*p)=φ(i)*(p-1))

    证明:

    2式可以直接由积性函数的性质(性质4)推出,1式证明如下:

    (i)转换为(p^n*k)的形式,则(φ(i)=p^{n}*frac{p-1}{p}*φ(k))(φ(i*p)=φ(p^{n+1}*k)),由于(p^{n+1})(k)互质,因此(φ(i*p)=φ(p^{n+1}*k)=φ(p^{n+1})*φ(k)=p^{n+1}*frac{p-1}{p}*φ(k)=p*φ(i))

    代码:

    //HDU1286,T组数据,询问n的欧拉函数,n<32768
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+5;
    const int maxp=1e6+5;
    bool isprime[maxn];
    int prime[maxp], primecnt = 0;
    int ol[maxn];
    void getOL(int n){//筛到n
    	memset(isprime, 1, sizeof(isprime));
    	isprime[1] = 0;//1不是素数
    	ol[1]=1;
    	for(int i = 2; i <= n; i++){
    		if(isprime[i]){//没筛掉
    			prime[++primecnt] = i; //i成为下一个素数
    			ol[i]=i-1;
    		}
    		for(int j = 1; j <= primecnt && i*prime[j] <= n; j++) {
    			isprime[i*prime[j]] = 0;
    			if(i % prime[j] == 0){//i中也含有prime[j]这个因子
    			    ol[i*prime[j]]=ol[i]*prime[j];
    				break;
    			}
    			else{
                    ol[i*prime[j]]=ol[i]*(prime[j]-1);
    			}
    		}
    	}
    }
    int main(){
        getOL(32768);
        int T;
        scanf("%d",&T);
        while(T--){
            int n;
            scanf("%d",&n);
            printf("%d
    ",ol[n]);
        }
    }
    

    引用与参考:

    https://blog.csdn.net/paxhujing/article/details/51353672

    https://www.cnblogs.com/Mychael/p/8759124.html

  • 相关阅读:
    【Spring】 AOP Base
    【Offer】[20] 【表示数值的字符串】
    【Offer】[19] 【字符串匹配】
    【设计模式】代理模式
    【LeetCode】[0002] 【两数之和】
    【Offer】[18-1] 【在O(1)时间内删除链表节点】
    【Offer】[18-2] 【删除链表中重复的节点】
    【Offer】[17] 【打印1到最大的n位数】
    【Offer】[16] 【数值的整数次方】
    python_内置函数
  • 原文地址:https://www.cnblogs.com/ucprer/p/13468287.html
Copyright © 2011-2022 走看看