素数筛法

求1和n之间的所有素数

1. 朴素方法

int m = sqrt(n + 0.5);
memset(vis, 0, sizeof(vis));
for(int i = 2; i <= m; i++) if(!vis[i])
   for(int j = i * i; j <= n; j += i) vis[j] = 1;

\(vis[i]\)表示\(i\)是否不是素数。
时间复杂度\(\sum_{i=2}^{\sqrt{n}} \frac{n}{i} = O(nlogn)\)

2. 线性筛

int pri[N], tot, np[N];
void sieve()
{
    np[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        if (!np[i]) pri[++tot] = i;
        for (int j = 1; j <= tot && i * pri[j] <= n; j++)
        {
            np[i * pri[j]] = 1;
            if (i % pri[j] == 0) break;
        }
    }
}

\(pri[i]\)表示第\(i\)个素数,\(np[i]\)表示\(i\)是否不是素数。
每次对数组np的赋值满足\(i\)\(i*pri[j]\)中的最小质因子,所以赋值不会重复。时间复杂度为\(O(n)\)

posted @ 2020-09-21 20:05  Sakyo  阅读(77)  评论(0)    收藏  举报