线性筛
先说一下素数的线性筛法,为了使每一个数都只被筛到一次,我们限定一下每个数是怎么被筛出来的:
对于$n=p_1^{k_1}p_2^{k_2} ....p_x^{k_x}(p_1到p_x单调递增)$,我们使得它由$\frac{n}{p_1}$筛得,这就是线性筛的基本思想。
代码:
1 int prim[maxn+10];//存素数 2 bool p[maxn+10];//p[i]=1表示i为合数,反之为素数 3 void prepare(void) 4 { 5 for (int i=2;i<=maxn;++i) 6 { 7 if(p[i]==0) 8 prim[++prim[0]]=i; 9 for (int j=1;j<=prim[0]&&i*prim[j]<=maxn;++j) 10 { 11 p[i*prim[j]]=1; 12 if(i%prim[j]==0)//当推到i的最小素因子后停止 13 break; 14 } 15 } 16 return ; 17 }
再介绍一下常用的2个数论函数如何用线性筛来求
1.欧拉函数
$\varphi(n)$表示[1,n]中与n互质的数的个数。
$\varphi(1)=1$
当p为素数时,$\varphi(p)=p-1$。
当gcd(a,b)=1时,$\varphi(ab)=\varphi(a)\varphi(b)$。
当n%p=0时(p为素数),$\varphi(np)=\varphi(n)p$
代码:
1 int prim[maxn+10],phi[maxn+10];//phi存欧拉函数的值 2 bool p[maxn+10]; 3 void prepare(void) 4 { 5 phi[1]=1; 6 for (int i=2;i<=maxn;++i) 7 { 8 if(p[i]==0) 9 prim[++prim[0]]=i,phi[i]=i-1; 10 for (int j=1;j<=prim[0]&&i*prim[j]<=maxn;++j) 11 { 12 p[i*prim[j]]=1; 13 if(i%prim[j]==0) 14 { 15 phi[i*prim[j]]=phi[i]*prim[j]; 16 break; 17 } 18 phi[i*prim[j]]=phi[i]*phi[prim[j]]; 19 } 20 } 21 return ; 22 }
2.莫比乌斯函数
$\mu(1)=1$
若n有平方因子,则$\mu(n)=0$
否则,若n为k个不同质数的积,则$\mu(n)=(-1)^k$
代码:
1 int prim[maxn+10],mu[maxn+10];//mu存莫比乌斯函数的值 2 bool p[maxn+10]; 3 void prepare(void) 4 { 5 mu[1]=1; 6 for (int i=2;i<=maxn;++i) 7 { 8 if(p[i]==0) 9 prim[++prim[0]]=i,mu[i]=-1; 10 for (int j=1;j<=prim[0]&&i*prim[j]<=maxn;++j) 11 { 12 p[i*prim[j]]=1; 13 if(i%prim[j]==0) 14 { 15 mu[i*prim[j]]=0; 16 break; 17 } 18 mu[i*prim[j]]=-mu[i]; 19 } 20 } 21 return ; 22 }
走着走着,就忘了自己的目的是什么

浙公网安备 33010602011771号