线性筛法 欧拉函数

线性筛法:

 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了

 

posted @ 2016-03-04 11:56  yanzx6  阅读(407)  评论(0编辑  收藏  举报