学习笔记--数论--欧式线性筛素数

线性筛法,

即是筛选掉所有合数,留下质数

我们知道合数可以由一个质数数与另一个数相乘得到,而比一个合数数大的质数和该合数的乘积可用一个更大的合数和比其小的质数相乘得到

这也是if(! ( i % prime[j]) )break;的含义,
这也是线性筛法算质数表的关键所在

原理:

  1. 任何一个合数都可以表示成一个质数和一个数的乘积

  2. 假设A是一个合数,且\(A = x * y\),这里x也是一个合数,那么有: \(A = x * y\); (假设y质数,x合数)
    $ x = a * b$; (假设a是质数,且a < x)-> $A = a * b * y = a * Z (Z = b * y) $
    即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积

    这也是理解代码中 \(if(i%primes[j] == 0)break;\)的关键

    例如: 如果i = 8; 那么由于i%2 == 0; 因此对于i=8就只需要检查\(primes[1]\)即可,因为对于大于\(primes[1]\)的质数,像3,有: $8×3 = 2×4×3 = 12×2 $ 也就是说\(24(8*3=24)\)并不需要在8时检查,在12时才检查

#include <iostream> 
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std; 
const int maxn=10000000+10;
int n,m;
bool is_Prime[maxn]; 
int total;//计数  
int primenum[maxn];//线性筛法寻找素数 
void pick_up_Prime() 
{ 
  memset(is_Prime,1,sizeof(is_Prime));
  memset(primenum,0,sizeof(primenum)); 
  is_Prime[0]=0;
  is_Prime[1]=0;//特判
   for(register int i=2;i<=n;i++) 
 { 
   if(is_Prime[i]) primenum[total++]=i;   
   for(register int j=0; j<total && i*primenum[j]<=n;j++)   
   { 
     is_Prime[i*primenum[j]]=0; 
      if(i%primenum[j]==0) break; } 
 }  
} 

int main()  
{  
 cin>>n>>m;
 pick_up_Prime();  
 for(register int i=1;i<=m;i++)
  {
      int x;
      scanf("%d",&x);
      if(is_Prime[x])puts("Yes");
      else puts("No");
  }
  return 0; 
} 

在洛谷上欧式筛法比埃式筛法跑的更快(至少我的是这样),但带来的是更多空间消耗。

posted @ 2018-02-27 14:57  Rye_Catcher  阅读(1159)  评论(0编辑  收藏  举报