(PPT上有严谨的定义,下文还有清晰的证明
on 2020.1 by li'ao
摘自PPT:
积性函数
(其中 Def 是 定义 的意思
(注意,要互质才行!
欧拉函数
(其中 Def 表示 “定义”)
通项公式:
(其中p1, p2……pn为x的所有质因数,x是不为0的整数)
当p是素数时,
易由通项公式变形得来
现证通项公式
由积性函数的性质:
若(a,b)=1,则(phi(a*b) = phi(a) * phi(b))
对于(phi(n)),标准分解,(phi(n) = phi(p_1^{alpha_1} * p_2^{alpha_2} * p_3 ^ {alpha_3} * ... * p_k ^ {alpha_k})),
按照积性函数的性质,上式等于:
以下证明(phi(p^alpha) = p^alpha - p^{alpha - 1})
因为p是质数,所以不与p互质的数都是p的倍数,在1~ (p^alpha) 中,(p) 的倍数有(p, 2 * p, 3 * p...(p ^ {alpha - 1}) * p)
共(p ^ {alpha - 1} 个)
所以在1 ~ (p ^ alpha)中,共有 (p ^ alpha - p ^ {alpha - 1})个数与p互质,
所以在1 ~ (p ^ {alpha} - 1)中,也有 (p ^ alpha - p ^ {alpha - 1})个数与p互质
所以(phi(p ^ alpha) = p ^ alpha * ( 1 - frac{1}{p}))
易知(phi(n) = phi(p_1^{alpha_1}) * phi(p_2^{alpha_2}) * phi(p_3^{alpha_3}) * ... * phi(p_k^{alpha_k} ) = (p_1 ^ {alpha_1} * p_2 ^ {alpha_2} * ... *p_k ^ {alpha_k}) * (1 - frac{1}{p_1}) * (1 - frac{1}{p_2}) ... * (1 - frac{1}{p_k}))
得证。
线性求欧拉函数
性质
1.若p是素数,则(phi(p) = p - 1)
2.(对于质数p和任意正整数i)若(i,p) = 1, 则(phi(i * p) = phi(i) * (p - 1))
3.(对于质数p和任意正整数i)若i, p 不互质,则(phi(i * p) = phi(i) * p)
(1,2都易知的啦
第三条性质证明
若 n 和 i 不互质,则 (n + i ) 和 i 不互质....................................................1)
[1,i]中,与i不互质的数的个数为: (i - phi(i))
(由1)得)对于其中任意一个与i不互质的整数n, n + i 和 i 也不互质, 对于其中任意一个与i互质的数, 它加上i 还是与i 互质,所以:在[1 + i, i + i]中,与i不互质的数的个数还是
对于一个素数p,前提条件,前提条件:i % p == 0,因为p是质数,所以i 是 p 的倍数(前提条件!
如此累加p个i,(其中p是素数),则在[1,p * i]中,与i 不互质的数的个数为
.....................................................................................................................2)
(稍微解释一下,就是对于任意k属于[0,p - 1],都有:在[1 + i * k, i + i * k]中与i不互质的数的个数为(i - phi(i)))
另一方面,[1, p * i]中与i * p不互质的数的个数为 (p * i - phi(p * i))..................3)
既然i是p的倍数,那么 2)式 等于 3)式
(解释一下:令i = p * k, i * p = k * p * p,
所以i 和 p * i 没有不同的因数
那么在[1, i * p]中,所有与k * p有公因数的数,必定也和 k * p * p 有公因数,即对于i 和 i * p, 在[1, i * p]中, 与他俩不互质的数的个数相等
得证。
代码实现
没错,就是根据3条性质来写代码
const int N = 300010;
int n, phi[N], pri[N], not_pri[N], top;
//这个函数是在线性欧拉素数筛的基础上写的,新加的东西只有 3行,(如果还不会线性素数筛,那就先看线性素数筛的模板
void Phi(int n){
not_pri[1] = 1;
F(i,2,n){
if(!not_pri[i]){
pri[++top] = i;
phi[i] = i - 1;//QWQ1
//i是素数,用到性质1
}
for(int j = 1; i * pri[j] <= n; j++){
not_pri[i * pri[j]] = 1;
if(i % pri[j]) phi[i * pri[j]] = phi[i] * (pri[j]- 1);//QWQ2
//因为pri[j]是素数,所以如果i % pri[j] != 0, 即i 是 pri[j] 的倍数, 那么i 和 pri[j] 就互质,用性质2
else{
phi[i * pri[j]] = phi[i] * pri[j];//QWQ3
//如果i 和 pri[j]不互质,用到性质3
break;
}
}
}
}
int main(){
cin >> n;
Phi(n);
F(i,1,n) cout << phi[i] << " ";
return 0;
}
推送题目:洛谷P2158