线性筛

先说一下素数的线性筛法,为了使每一个数都只被筛到一次,我们限定一下每个数是怎么被筛出来的:

        对于$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 }

 

posted @ 2017-07-06 08:45  Y_AMTUCS  阅读(144)  评论(0)    收藏  举报