欧拉函数:
- 欧拉函数定义: 1~n中与n互质的数的个数。 比如
- 欧拉函数是积性函数:(也就是)当 n与m互质的时候:
- 由算术基本定理,我们可以设n=,那么我们只要计算出的取值就能求出的取值。 下面给出证明
的取值怎么求? 也就是求1~中与互质的数的个数
我们可以求与不互质的数的个数,由于p是质数,所以与不互质的数一定是p的倍数
那么1~中,p的倍数就是 , 那么我们就知道与不互质的数的个数 就是。也就是
由于之间互质,且欧拉函数是一个积性函数,那么有
所以我们只需要求出n的所有质因子p,然后求出 的乘积即可
phi = n;
for(int i=2 ; i*i<=n ; i++ )
if( n%i == 0 ){
phi = phi/i * (i-1 ) // 1- 1/p == (p-1)/p 为了防止爆int,故意不写成phi*(i-1)/i
while ( n%i==0 ) n/=i ;
}
if(n!=1) phi =phi/n *(n-1); //防止n有一个大于 sqrt(n)的质因子的情况
以上就是试除法求欧拉函数的板子,请牢牢记住,后面回经常用到。
下面介绍筛法求欧拉函数,可以以O(n)的时间来求2~n的欧拉函数。
const int N = 1e6 + 7;
int pri[N], phi[N], flag[N];
int tot;
int main() {
phi[1]=1;
for (int i = 2; i <= N; i++) {
if (flag[i] == 0) {
pri[tot++] = i;
phi[i] = i - 1;
}
for (int j = 0; j < tot and pri[j] * i <= N; j++) {
if (i % pri[j] == 0) {
phi[i * pri[j]] = pri[j] * phi[i];
flag[i * pri[j]] = 1;
break;
}
else {
flag[i * pri[j]] = 1;
phi[i * pri[j]] = (pri[j] - 1) * pri[i];
}
}
}
}
下面逐步分析这个板子:
首先我们需要写出一个线性筛的板子,然后根据欧拉函数的定义填充即可:
if (flag[i] == 0) {
pri[tot++] = i;
phi[i] = i - 1;
}
这里很简单,当i是质数的时候,我们将i假如质数表,并且写上i的欧拉函数为i-1,phi[i]=i-1
for (int j = 0; j < tot and pri[j] * i <= N; j++) {
if (i % pri[j] == 0) {
phi[i * pri[j]] = pri[j] * phi[i];
flag[i * pri[j]] = 1;
break;
}
else {
flag[i * pri[j]] = 1;
phi[i * pri[j]] = (pri[j] - 1) * pri[i];
}
}