筛选法与预处理

问题引入


给定整数N(1<N<100000),输出所有素数.

本题可以用暴力求解,但是显然在竞赛中是不可取的,因为复杂度接近O(n^2)
从另一角度思考,素数的倍数一定不是素数。可以先将数据存储在一个数组中,标定0为素数,1为非素数。数组从2开始遍历,如果n[i]=0,则将所有n[i]的倍数都标记为1,以此类推。最后为0的便是素数。
代码如下

/*用筛选法求100000以内的所有素数*/
#include<stdio.h>
int main()
{
  int n[100001] = {0};
  int i,j;
  for(i=2;i<=100000;i++)
  {
    if(n[i] == 0)
    {
      for(j=i*2;j<=100000;j+=i)
      {
        n[j] = 1;
      }
    }
  }
  for(i=2;i<=100000;i++)
  {
    if(n[i] == 0) printf("%d\n",i);
  }
}

这样复杂度会大大降低,但是还有可以优化的地方。

/*用筛选法求100000以内的所有素数*/
#include<stdio.h>
#include<math.h>
int main()
{
    int n[100001] = {0};
    int i,j;
    for(i=2;i<=(int)sqrt(100000);i++)  
    {
        if(n[i] == 0)
        {
            for(j=i*i;j<=100000;j+=i)
            {
                n[j] = 1;
            }
        }
    }
    for(i=2;i<=100000;i++)
    {
        if(n[i] == 0) printf("%d\n",i);
    }
}

这样复杂度更低了。

当题目要求求很多组数据,则可以在第一次将所有结果保存在一个数组中,这样就免去了每一组数据求一次解的步骤。这便是预处理。

... ... ...