/* 返回顶部 */

欧拉函数

原文:2018-12-18

欧拉函数是小于\(n\)的整数中\(n\)互质的数的个数,一般用\(\varphi(n)\)表示。
通式:

\[\varphi(n) = n(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_k}) \]

其中\(p_1, p_2……p_k\)\(n\)的所有质因数,\(n\)是不为\(0\)的整数。

例如\(n=12=2*2*3\)
\(12\)以内有\(1/2\)的数是\(2\)的倍数,那么有\(1-1/2\)的数不是\(2\)的倍数\((1,3,5,7,9,11)\)
\(6\)个数里又有\(1/3\)的数是\(3\)的倍数,
只剩下\((1 - 1/2 - 1/3)\)的数既不是2的倍数,也不是3的倍数\((1,5,7,11)\)
这样剩下的\(12*(1 - 1/2 - 1/3)=4\),即\(4\)个数与\(12\)互质,所以\(\varphi(12)=4\)

证明:

  • 如果\(n=1\),则\(\varphi(1) = 1\)
  • 如果\(n\)是质数,则\(\varphi(n)=n-1\)
    反之,若\(\varphi(n)=n-1\),则\(n\)是质数。
  • 如果\(n\)只有一个质因数\(p\),即\(n = p^k(k\ge 1)\),则\(\varphi(n)=p^k(1-\frac{1}{p})=p^k-p^{k-1}\)
    • \([1,n]\)中,\(p\)的倍数共有\(n/p\)个,共占了\(\frac{1}{p}\),则减去这些数后,还剩下\(n*(1-\frac{1}{p})\)个。
      可以看出,\(n\)是质数相当于\(k=1\)时的特例。
  • 欧拉函数是积性函数,即对于\(n=p_1*p_2*...*p_n\) \((p_i分别互质)\)

\[\varphi(n) = \varphi(p_1) * \varphi(p_2) *...* \varphi(p_k) \]

\[= p_1(1-\frac{1}{p_1})*p_2(1-\frac{1}{p_2})*...*p_k(1-\frac{1}{p_k}) \]

\[= n(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_k}) \]

性质:

  • \(n>2\)时,\(\varphi(n)\)是偶数。
  • \(n\)为奇数,\(\varphi(2n)=\varphi(n)\)
  • \(n\)的因数(包括\(1\)\(n\))的欧拉函数之和等于\(n\)
    \(\sum_{d|n}\varphi(d) = n\)
  • \((1,n)\)中,与\(n\)互质的数的总和为 \(\dfrac{\varphi(n)*n}{2}\)
    因为\(gcd(n,i)=gcd(n,n-i)\),即若\(i\)\(n\)互质,则\(n-i\)也与\(n\)互质。
  • 欧拉定理:对于任何两个互质的正整数\(a,n(n>2)\),有:\(a^{\varphi(n)}\equiv 1\pmod n\)
  • 费马小定理:在上式的基础上,当\(n\)是质数时(即\(\varphi(n) = n-1\)),有: \(a^{n-1}\equiv 1\pmod n\)
  • 扩展欧拉定理

求欧拉函数:

埃拉托斯特尼筛 \((Eratosthenes)\)

\([1,n]\)所有数的欧拉函数:每次找到一个质数,就把它的倍数更新掉。复杂度大概是\(O(nlogn)\)

void euler(int n) {
    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)
                phi[j]=phi[j]/i*(i-1);
}

线性筛

\(p\)为素数,则有

  • \(\varphi(p) = p-1\)
  • 如果\(i\)\(p\)互质, 那么 \(\varphi(i * p) = \varphi(i) * (p-1)\)
  • 如果\(i\)\(p\)不互质, 那么\(\varphi(i * p) = \varphi(i) * p\)

复杂度为\(O(n)\)

void get_phi(long long n) {
	p[1] = 1;
	for(long long i = 2; i <= n; i++) {
		if(!flag[i]) {
			prime[++cnt] = i;
			p[i] = i-1;
		}
		for(long long j = 1; j <= cnt && i*prime[j] <= n; j++) {
			flag[i*prime[j]] = true;
			if(i%prime[j])
				p[i*prime[j]] = p[i]*(prime[j]-1);
			else {
				p[i*prime[j]] = p[i]*prime[j];
				break;
			}
		}
	}
}

通项公式

\(n\)的欧拉函数:每次找到一个最小的因数(一定为质因数),求出\(n*(1-\frac{1}{p})\)。复杂度为\(O(\sqrt n)\)

int euler(int n) {
    int res=n,a=n;
    for(int i=2; i*i<=a; i++) {
        if(a%i==0) {
            res=res/i*(i-1);
            while(a%i==0) a/=i;
        }
    }
    if(a>1) res=res/a*(a-1); //有质数剩余 
    return res;
}

为了保证每个质因数只被使用一次,通过以上的while循环把\(n\)中的\(p_i\)除尽。

posted @ 2020-07-02 11:46  Mogeko  阅读(170)  评论(0编辑  收藏  举报