求素数的几种方法 ——(线性筛法)

求N以内的 所有素数(N <=1000000)

 求素数的方法1: 暴力

#include
#include
#include
#include
using namespace std;
int su[1000010];
int prime(int n)
{
    for(int i=2;i

 当然为了提高代码运行的速度 可以对n 进行sqrt(); 如果d为n的 一个因数,那么n/d也  是n 的一个因数。max(d,n/d)<=sqrt(n);

#include
#include
#include
#include
#include
using namespace std;
int su[1000010];
int prime(int n)
{
    for(int i=2;i<=sqrt(n);i++)
    {
        if(n%i==0)
            return 0;
    }
    return 1;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int r=0;
        for(int i=2;i<=n;i++)
        {
            if(prime(i))
               su[r++]=i;
        }
        for(int i=0;i

开根号确实 可以提高 运算速度,但是还是达不到我们想要的 效果。然后就开始看筛法。

所有的素数的倍数肯定 不是素数。

所以我们 每次找到一个素数,就把他的所有的倍数都删除了。

例如:

数组a:              1    2    3    4    5     6    7     8    9    10

book数组:      1    0    0    0    0     0    0     0    0     0  【因为1不是素数,所以标记为1】

 2为素数:

数组a:              1    2    3    4    5     6    7     8    9    10

book数组:      1    0    0    1    0     1    0     1    0     1  【把素数2的倍数全部标记成1】

寻找下一个素数 3:

数组a:              1    2    3    4    5     6    7     8    9    10

book数组:      1    0    0    1    0     1    0     1    1     1  【把素数3的倍数也全部标记成1】

以此类推。

#include
#include
#include
#include
#include
using namespace std;
int su[1000010];
bool book[1000010];
int r;
int prime(int n)
{
    r=0;
    memset(book,0,sizeof(book));
    book[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(book[i]==0)
        {
            su[r++]=i;
            for(int j=i*2;j<=n;j+=i)
                book[j]=1;
        }
    }
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        prime(n);
        for(int i=0;i

这个代码还可以改进。
第一,我们不用筛到n,其实只要和暴力方法一样,筛到sqrt(n)就可以了。
第二,我们筛3时多筛了3*2,筛5时多筛了5*2,5*3,5*4。只要从i*i开始筛就可以了。

#include
#include
#include
#include
#include
using namespace std;
int su[1000010];
bool book[1000010];
int r;
int prime(int n)
{
    r=0;
    memset(book,0,sizeof(book));
    book[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(book[i]==0)
        {
            su[r++]=i;
            for(int j=i*i;j<=n;j+=i)
                book[j]=1;
        }
    }
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        prime(n);
        for(int i=0;i

应该还存在比着速度更快的算法,但是吧,由于本人太菜了。。。不会q@q

上面我们用的是素数的倍数肯定不是素数,构造的一种筛选的方法。

接下来换一种更高效的筛选构造法;https://www.cnblogs.com/juicebox/p/9644484.html 【详细解说】

用素数 的倍数一定不是素数来构造还存在一些问题。

比如筛30的时候,在 i=2 的时候, k = 2 * 15 筛了一次;在 i=5, k = 5 * 6 的时候又筛了一次。接下来换一种筛选方法消除这些问题。

核心思想所有的合数可以表示为两个或多个素数的积。(实际上也相当于合数等于素数乘一个比它小的合数)

实现:我们遍历每个数,把它与之前找到的素数相乘,把相乘的结果标记为合数。


​
#include
#include
#include
#include
#include
using namespace std;
#define N 1000010
int su[N];
bool book[N];
int r;
int prime(int n)
{
    r=0;
    memset(book,0,sizeof(book));
    book[1]=1;
    for(int i=2; i

 

你可能感兴趣的:(数论)