欧拉函数和线性欧拉筛
欧拉函数和线性欧拉筛
欧拉函数
定义
欧拉函数本质上表示了小于等于 \(n\) 的正整数中与 \(n\) 互质的个数
注意:欧拉函数在互质时是积性函数,非互质时不是积性函数:
推论
-
推论 \(1\):对于质数 \(p\),有:
\[\phi(p)=p-1 \]证明:
即 \(1,2,\cdots,p−1\) 与 \(p\) 互质
-
推论 \(2\):对于质数 \(p\),有:
\[\phi(p^k)=p^{k-1}\times\phi(p)=p^{k-1}\times(p-1)=p^{k}\times\cfrac{p-1}{p} \]证明:
在 \([1,p^k]\) 中,与 \(p^k\) 不互质的数均为 \(p\) 的倍数,有 \(\cfrac{p^k}{p}=p^{k-1}\) 个,所以:
\[\phi(p^k)=p^k-p^{k-1}=p^{k-1}\times(p-1) \] -
推论 \(3\):推广至两个不同质数 \(a\) ,\(b\) ,有:
\[\phi(a\times b)=\phi(a)\times \phi(b)=a\times b\times \cfrac{a-1}{a}\times \cfrac{b-1}{b} \]证明:
根据推论 \(1\) 与欧拉函数的积性:
\[\phi(a\times b)=\phi(a)\times\phi(b)=(a-1)\times(b-1)=a\times b\times \cfrac{a-1}{a}\times \cfrac{b-1}{b} \] -
推论 \(4\):继续推广,设 \(n=p_1^{k_1}\times p_2^{k_2}\times\cdots\times p_n^{k_n}\)(正整数 \(n\) 的标准分解式) ,则有:
\[\phi(n)=n\times\prod^n_{i=1}\cfrac{p_i-1}{p_i} \]证明:
根据推论 \(2\) 与欧拉函数的积性:
\[\phi(p_i^{k_i})=p_i^{k_i}\times\cfrac{p_i-1}{p_i} \]所以,将所有质因子贡献相乘:
\[\phi(n)=\prod_{i=1}^{n}\phi(p_i^{k_i})=\prod_{i=1}^{n}(p_i^{k_i}\times\cfrac{p_i-1}{p_i})=n\times\prod^n_{i=1}\cfrac{p_i-1}{p_i} \]
算法实现
根据 推论 \(4\) ,可以发现求欧拉函数重点在求 \(n\) 的质因数
int ans = n;
for (int i = 2;i * i <= n;i ++) { // 枚举因数
if (n % i == 0) ans = ans / i * (i - 1); // 应用公式
while (n % i == 0) n /= i; // 剔除所有该因子
}
if (n > 1) ans = ans / n * (n - 1); // 处理剩余因子
欧拉函数筛
欧拉函数筛其实是建立在线性质数筛的基础上的
这时考虑与线性筛相似的一个问题:如何通过 \(\phi(i)\) 求出 \(\phi(i\times p)\) (\(p\) 为小于等于 \(i\) 的质数)
分情况讨论:
-
\(p\mid i\):
设 \(i=p^k\times m\quad(\gcd(m,p)=1)\):
将 \(\phi(i)\) 展开:
\[\phi(i)=\phi(p^k\times m)=\phi(p^k)\times \phi(m)=p^{k-1}(p-1)\times\phi(m)\tag1 \]将 \(\phi(i\times p)\) 展开:
\[\phi(i\times p)=\phi(p^{k+1}\times m)=\phi(p^{k+1})\times\phi(m)=p^k(p-1)\times\phi(m)=p(p^{k-1}(p-1)\times\phi(m))\tag2 \]将 \(1\) 式中的 \(p^{k-1}(p-1)\times\phi(m)=\phi(i)\) 代入 \(2\) 式:
\[\phi(i\times p)=p\times\phi(i) \] -
\(p\nmid i\):
根据欧拉函数的积性:
\[\phi(i\times p)=\phi(i)\times\phi(p)=\phi(i)\times(p-1) \]
int phi[maxn],prime[maxn],cnt = 0; // 统计欧拉函数与质数
bool notprime[maxn]; // (线性质数筛)
phi[1] = 1;
for(int i = 2;i <= n; ++i) {
if(!notprime[i]) prime[++cnt] = i,phi[i] = i - 1; // 质数的情况 (i - 1)
for(int j = 1;j <= cnt && i * prime[j] <= n; ++j) { // (线性质数筛)
notprime[i * prime[j]] = 1; // (线性质数筛)
if(i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j]; // p|i
break; // (线性质数筛)
} else phi[i * prime[j]] = phi[i] * (prime[j] - 1); // p !| i
}
}
欧拉定理
令 \(m\) 为一个正整数,\(a\) 为一个整数,且 \(a\),\(p\) 互质,则:
当 \(p\) 为质数时,由**推论 \(1\) **得 \(\phi(p)=p-1\),所以:
这就是费马小定理
扩展欧拉定理
扩展欧拉定理可以解决 \(a^b\mod p\) 中指数过大的问题
例题
这道题可以采用递归逐步求解平方的做法:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1234567;
const int mod0 = 10007;
int n;
int a[maxn + 5];
int phi[maxn];
int prime[maxn], cnt; bool notprime[maxn];
void Getphi(int n) {
phi[1] = 1;
for(int i = 2;i <= n; ++i) {
if(!notprime[i]) prime[++cnt] = i; phi[i] = i - 1;
for(int j = 1;j <= cnt && i * prime[j] <= n; ++j) {
notprime[i * prime[j]] = 1;
if(i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
} else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
int fastPow(int a,int b,int mod) {
if (b == 0) return 1;
if (b == 1) return a % mod;
int x = fastPow(a,b / 2,mod);
x = (x % mod * x % mod) % mod;
if (b % 2 != 0) x = (x % mod * a % mod) % mod;
return x;
}
int solve(int i,int mod) {
if (i == n + 1) return 1;
return fastPow(a[i],solve(i + 1,phi[mod]),mod);
}
int main() {
memset(notprime,false,sizeof(notprime));
scanf("%d",&n);
Getphi(mod0);
for (int i = 1;i <= n;i ++) scanf("%d",&a[i]);
printf("%d",solve(1,mod0) % mod0);
return 0;
}

浙公网安备 33010602011771号