欧拉筛(线性筛)求莫比乌斯函数μ

欧拉筛


筛法我们肯定都不陌生,用来求一定序列内素数个数的方法麻,但在学习完埃氏筛法后(如果没学过可以去学一下再看),我们发现它似乎做了很多多余的操作,一个数会被他的质所有筛

一遍,但我们本质上筛一遍就够了,所以我们有没有什么方法去优化它呢?欧拉筛随之而出,欧拉筛的特点便是一个数只会被它的最小质因子筛一遍,其它质因子不会筛它,这便大大提高了时

间效率

代码如下

(懒的不想写便把这个博客里的代码搬了一下)

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];
        }
    }

介绍到这里啦,完结撒花!

原文地址:https://www.cnblogs.com/rpup/p/13557308.html