欧拉函数的定义
在数论中,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目.
欧拉函数的重要性质
- 若(即m与n互质),则
- 若为质数,则
- 若为质数,则
对于性质2,若为质数,则小于的个数都互质,所以
根据性质3,若为质数,则在中,只有p的倍数与不互质,则
的欧拉函数就等于总数-p的倍数,我们发现以做为一个周期循环节,每个循环节共有p-1个,则,化简得
欧拉函数的计算
根据整数惟一分解定理,
所以欧拉函数仅由n和质因子决定,与次数无关。
根据公式我们有试除法求欧拉函数:
int phi(int n) {
int res = n;
for(int i = 2; i <= n / i; i++){
if(n % i == 0){
res = res / i * (i - 1);
while(n % i == 0) n /= i;
}
}
if(n > 1) res = res / n * (n - 1);
return res;
}
最后回归主题,筛法求欧拉函数,通过线性筛在线性的时间内求出1-n每个数的欧拉函数。
根据上文,当i是质数,。
在线性筛中,每个合数都是被最小质因子筛掉的,那么设有是的最小质因子,则是通过筛掉的
- 若能被整除,则i包含了m所有的质因子
- 若不能被整除,则与是互质的
由上则代码如下,时间复杂度O(n):
const int N = 1e6 + 9;
int p[N], phi[N], cnt;
bool vis[N];
void get_phi(int n) {
phi[1] = 1;
for(int i = 2; i <= n; i++) {
if(!vis[i]) {
p[cnt++] = i;
phi[i] = i - 1;
}
for(int j = 0; p[j] <= n / i ; j++) {
int m = i * p[j];
vis[m] = 1;
if(i % p[j] == 0) {
phi[m] = p[j] * phi[i];
break;
} else {
phi[m] = (p[j] - 1) * phi[i];
}
}
}
}