线性筛法与欧拉函数
标签(空格分隔): 数论
一、引入
我们已经很熟悉Eratosthenes筛法(埃拉托斯特尼筛法),其基本思想是,每次筛去一个指数的所有倍数,如对于质数2,筛去4,6,8等等,对于质数3,筛去6,9,12等等。
其弊端也显而易见,6和12等等数字,均被筛去的多次,这样就造成了重复,复杂度不够好。
有没有更快的筛法,当然有。
二、说在前面
对于任何一个数字,我们都能利用唯一分解定理将其拆分。对于合数来说,其因子数量大于等于2个,如最小的合数4可以拆分为2*2 , 6可以拆分为2*3.
于是对于任何的合数
n
,我们用以下的方法进行表示:
其中 pmin 是 n 的最小质数。例如
如此的规定不是无故为之的,如果每个合数都被其最小的质因数筛去,那么就会保证不重不漏。换言之,若我们对于质数2,将所有以2为最小质因数的合数筛去,对于质数3,将所有以2为最小质因数的合数筛去,如此就可以保证不会重复筛一个数。
如何实现呢?
三、代码实现
memset(check,false,sizeof check);
int tot = 0;
for(int i = 2;i<=N;++i) {
if(!check[i]) prime[tot++] = i;
for(int j = 0;j<tot;++j) {
if( i * prime[j] > N ) break;
check[ i * prime[j] ] = true;
if( i % prime[j] == 0 ) break;
}
}
其中第八行的if( i % prime[j] == 0 ) break;可谓精髓。
可以见得? 当i为4时,首先筛掉的是8,而此时 i % 2等于0,跳出内层循环,否则的话,就会筛掉12,而我们知道,12应该在因子为2的时候筛掉,而不是3的时候被筛掉,这样一来保证了复杂度。
四、欧拉函数
欧拉函数指的是:对一个正整数
n
,小于
如
φ(24)=8
,因为1, 5, 7, 11, 13, 17, 19, 23均和 24 互质。
下面介绍一些基本性质:
其中加**表示在求欧拉函数的时候会用得到。
1.
n≥1,φ(1)=1
。
2. **当
n
为质数的时候,
3. **欧拉函数是积性函数,但不是完全积性。当
n,m
互质的时候,
φ(n∗m)=φ(n)∗φ(m)
。
4. 当n为奇数的时候,
φ(2∗n)=φ(n)
。
5. 除了
φ(2)
时,其他欧拉函数均为偶数。
6. 小于
n
,且与
可以在线性筛法中,加入求欧拉函数的内容。
五、代码拓展
memset(check,false,sizeof check);
int tot = 0;
phi[1] = 1;
for(int i = 2;i<=N;++i) {
if(!check[i]){
prime[tot++] = i;
phi[i]= i-1;
}
for(int j = 0;j<tot;++j) {
if( i * prime[j] > N ) break;
check[ i * prime[j] ] = true;
if( i % prime[j] == 0 ) {
phi[ i * prime[j] ] = phi[i] * prime[j] ;
break;
}else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
第7行参考性质2
第15行参考性质3
好好理解一下第13行