线性筛法 欧拉函数
线性筛法:
1 for(int i = 2; i < MAXPRIME; i++)
2 {
3 if(!visit[i]) prime[tot++] = i;
4 for(int j = 0; j < tot; j++)
5 {
6 if(i * prime[j] >= MAXPRIME) break;
7 visit[i * prime[j]] = 1;
8 if(!(i % prime[j])) break;
9 }
10 }
如何理解?
考虑每一个合数都可以表示为质数和另一个数的积
即x=p*a,特别的,这里我们令p为x的最小质数
对于每一个a,如果我们有a%p==0,那么我们就不用枚举下去了
因为a%p1==0,枚举下去,a*p2 = p1 * ((a / p1) * p2)
这样p1才是a*p2的最小质因子,也会被枚举到
所以每个数只会被标记一次,访问一次,是线性的
欧拉函数phi(x)表示1-X中 gcd(x, i)==1的数目
首先,显然
考虑一个质因子时,是显然的
考虑两个质因子时,令x = p1 * p2
如果去除p1的倍数,去除了p2个,也就是p1|gcd(x, i)的那些数
如果去除p2的倍数,去除了p1个,也就是p2|gcd(x, i)的那些数
这些数有一个数重复了,就是p1*p2,共去除p1+p2-1个
考虑另一种想法(也就是式子中的算法)
先去除p1的倍数,去除p2个,这时剩下p1*p2-p2个数,
剩下的数里面,每p2个数,就有一个p2的倍数,去除(p1*p2-p2)/p2个数
加起来也就是p1+p2-1个数
当x = p1^k1 * p2^k2时,相当于将p1*p2的情况重复多次,一样满足
考虑多个质因子时,也是类似的。
那么根据这个式子,phi(x)是一个积性函数,当gcd(a, b) == 1时,phi(a*b) = phi(a) * phi(b)
再说一下其他性质
当x为质数时,显然phi(x) = x-1
当x%p==0时,其中p为质数,且为x的最小质因子,(重要关键点)
phi(x * p) = phi(x) * p
证明:
首先考虑phi(x)的那些数都为 gcd(y, x) ==1
那么gcd(x + y, x) == 1根据辗转相除法也是成立的
因为gcd(y, x) == 1,所以gcd(y, p) == 1
所以gcd(y, x * p) == 1
所以gcd(y + x, x * p) == 1
同理 gcd(y + x, x * p) == gcd(y + 2x, x * p) == gcd(y + 3x, x * p) == .... = gcd(y + (p - 1) * x, x * p) == 1
相当于证明了对于每一个gcd(y, x) ==1,都对应与p个与x*p互质的数,分别为y,y+x,y+2x,....y+(p-1)*x
得证
当x%p != 0时,即gcd(x, p) == 1
所以phi(x * p) = phi(x) * phi(p) = phi(x)*(p-1)
也可以用划掉含有p这个约数的数的思想去做
因为gcd(x, p) == 1
所以phi(x)的那几个数即为phi1,phi2,phi....phik
考虑phi1,phi2,phi....phik,phi1+x,phi2+x,phi+x....phik+x....phi1+2x,phi2+2x,phi+2x....phik+2x.......这phi(x)*p个数
要划去phi1 * p, phi2 * p ...... phik * p,这些数都有gcd(x, phii*p) == 1, gcd(phii*p, p) == p的性质
所以gcd(x*p, phii * p) == p,要划去
共phi(x)个
根据上述性质,就可以利用线性筛法求出phi(x),1<=x<=n了