线性筛法 欧拉筛c语言,线性筛法(欧拉筛)

从前有一个素数筛法叫埃拉托斯特尼筛法,它的思想很简单,把1-n以内素数的整数倍的数字划掉,留下的就全是素数,但是它的复杂度是O(NlglgN),对于大量不友好数据会跪,于是线性晒登场了。

#include

using namespace std;

int prime[1100000],primesize,phi[11000000];

bool isprime[11000000];

void getlist(int listsize)

{

memset(isprime,1,sizeof(isprime));

isprime[1]=false;

for(int i=2;i<=listsize;i++)

{

if(isprime[i])prime[++primesize]=i;

for(int j=1;j<=primesize&&i*prime[j]<=listsize;j++)

{

isprime[i*prime[j]]=false;

if(i%prime[j]==0)break;

}

}

}

以上就是线性晒代码,他与埃氏筛法大概有这么几点不同:

①:if(i%prime[j]==0)break;

这句代码保证了每个数最多被筛一次,将时间复杂度降到了线性。

证明如下:prime[]数组中的素数是递增的,当i能整除prime[j],那么i*prime[j+1]这个合数肯定被prime[j]乘以某个数筛掉。

因为i中含有prime[j],prime[j]比prime[j+1]小,即i=k*prime[j],那么i*prime[j+1]=(k*prime[j])*prime

[j+1]=k’*prime[j],接下去的素数同理。所以不用筛下去了。因此,在满足i%prime[j]==0这个条件之前以及第一次

满足改条件时,prime[j]必定是prime[j]*i的最小因子。

大名鼎鼎的线性晒日常筛素数的速度大概是埃氏筛的3-4倍,然而在小数据中却有被完爆的可能QAQ

所以欧拉筛法不只是拿来筛个素数,更重要的一点是线性筛可以用来求解积性函数。

积性函数f(x)应满足f(a×b)=f(a)×f(b),a与b应互素。而完全积性函数则应满足对于任意的a与b,前面的等式应成立。

先上欧拉phi函数:

memset(check,false,sizeof(check));

fai[1] = 1;

int tot = 0;

for(int i = 2 ; i <= N ; i++)

{

if(! check[i])

{

prime[tot++] = i;

fai[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){

fai[i * prime[j]] = fai[i] * prime[j];

break;

}

else{

fai[i * prime[j]] = fai[i] * (prime[j] - 1);

}

}

}再来个线性筛解莫比乌斯函数:

memset(check,false,sizeof(check));

mu[1] = 1;

int tot = 0;

for(int i = 2 ; i <= N ; i++)

{

if(! check[i])

{

prime[tot++] = i;

mu[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){

mu[i * prime[j]] = 0;

break;

}

else{

mu[i * prime[j]] = -mu[j];

}

}

}

你可能感兴趣的:(线性筛法,欧拉筛c语言)