欧拉筛(线性筛)求莫比乌斯函数μ
欧拉筛
筛法我们肯定都不陌生,用来求一定序列内素数个数的方法麻,但在学习完埃氏筛法后(如果没学过可以去学一下再看),我们发现它似乎做了很多多余的操作,一个数会被他的质所有筛
一遍,但我们本质上筛一遍就够了,所以我们有没有什么方法去优化它呢?欧拉筛随之而出,欧拉筛的特点便是一个数只会被它的最小质因子筛一遍,其它质因子不会筛它,这便大大提高了时
间效率
代码如下
(懒的不想写便把这个博客里的代码搬了一下)
for( int i=2;i<=n;i++ ) {
if( !death[i] )
primelist[++tail] = i;//record this new prime
for( int k=1;k<=tail;k++ ) {
if( primelist[k]*i > n ) break;
death[primelist[k]*i] = 1;
if( i%primelist[k] == 0 ) break;//!!!
}
}
death为我们的标记数组
欧拉筛相比埃氏筛的优点便在与if( i%primelist[k] == 0 ) break;这一句
当primelist[k]>primelistk1
时,因为primelist[k1]是i的最小质因子,所以它也是primelist[k]*i的最小质因子
所以primelist[k]i会由primelist[k1]某个i更新出来,所以当primelist[k]>primelist[ k1 ]时我们break;
将拒绝重复计算,而i*比他最小质因子小的质数,则是在更新以该质数为最小质因子的合数。
利用线性筛求莫比乌斯函数
我们来做一点小练习
利用线性筛求莫比乌斯函数
mu[1]=1;
for (int i=2;i<=10000000;i++) {
if (!flag[i]) prime[++cnt]=i,mu[i]=-1;
for (int j=1;j<=cnt&&i*prime[j]<=10000000;j++) {
flag[i*prime[j]]=1;
if (i%prime[j]==0) break;
mu[i*prime[j]]=-mu[i];
}
}
介绍到这里啦,完结撒花!