欧拉函数
原文: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\)时的特例。
- \([1,n]\)中,\(p\)的倍数共有\(n/p\)个,共占了\(\frac{1}{p}\),则减去这些数后,还剩下\(n*(1-\frac{1}{p})\)个。
- 欧拉函数是积性函数,即对于\(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\)除尽。