线性筛选法求素数表



  1.   
</pre>1.先介绍普通的算法,比较简单,直接贴代码</p><p></p><p></p><div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><strong>[cpp]</strong> <a target=_blank title="view plain" class="ViewSource" href="http://blog.youkuaiyun.com/qcgrxx/article/details/7388823#">view plain</a><a target=_blank title="copy" class="CopyToClipboard" href="http://blog.youkuaiyun.com/qcgrxx/article/details/7388823#">copy</a><a target=_blank title="print" class="PrintSource" href="http://blog.youkuaiyun.com/qcgrxx/article/details/7388823#">print</a><a target=_blank title="?" class="About" href="http://blog.youkuaiyun.com/qcgrxx/article/details/7388823#">?</a></div></div><ol class="dp-cpp"><li class="alt"><span><span class="preprocessor">#include <iostream>  </span><span>  </span></span></li><li><span>  <span class="keyword">using</span><span> </span><span class="keyword">namespace</span><span> std;    </span></span></li><li class="alt"><span>     </span></li><li><span>  <span class="keyword">const</span><span> </span><span class="datatypes">int</span><span> MAX=100;    </span></span></li><li class="alt"><span>  <span class="datatypes">bool</span><span> isPrime[MAX+1];    </span></span></li><li><span>  <span class="datatypes">int</span><span> total;</span><span class="comment">//计数  </span><span>  </span></span></li><li class="alt"><span>  <span class="datatypes">int</span><span> prime[MAX+1];   </span></span></li><li><span><span class="keyword">void</span><span> makePrime1()  </span></span></li><li class="alt"><span>{  </span></li><li><span>    memset(isPrime, 1, <span class="keyword">sizeof</span><span>(isPrime));  </span></span></li><li class="alt"><span>    isPrime[0]=<span class="keyword">false</span><span>;  </span></span></li><li><span>    isPrime[1]=<span class="keyword">false</span><span>;  </span></span></li><li class="alt"><span>    <span class="keyword">for</span><span> (</span><span class="datatypes">int</span><span> i=2;  i<=MAX;  i++)  </span></span></li><li><span>        <span class="keyword">if</span><span> (isPrime[i]) {  </span></span></li><li class="alt"><span>            prime[total++]=i;  </span></li><li><span>            <span class="keyword">for</span><span> (</span><span class="datatypes">int</span><span> k=i*i; k<=MAX; k+=i)  </span></span></li><li class="alt"><span>                 isPrime[k]=<span class="keyword">false</span><span>;  </span></span></li><li><span>        }  </span></li><li class="alt"><span>}   </span></li></ol></div><pre class="cpp" style="display: none;" name="code">#include <iostream>  
  using namespace std;  
   
  const int MAX=100;  
  bool isPrime[MAX+1];  
  int total;//计数  
  int prime[MAX+1]; 
void makePrime1()
{
    memset(isPrime, 1, sizeof(isPrime));
    isPrime[0]=false;
    isPrime[1]=false;
    for (int i=2;  i<=MAX;  i++)
        if (isPrime[i]) {
            prime[total++]=i;
            for (int k=i*i; k<=MAX; k+=i)
                 isPrime[k]=false;
        }
} 

2.线性筛选法

1)原理:
      i. 任何一个合数都可以表示成一个质数和一个数的乘积
     ii. 假设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)的乘积
    
2)代码:

  1. void makePrime2()    
  2. {    
  3.     memset(isPrime,true,sizeof(isPrime));    
  4.     memset(prime,0,sizeof(prime));    
  5.     for(int i=2;i<=MAX;i++)    
  6.     {    
  7.         if(isPrime[i]) prime[total++]=i;   
  8.         for(int j=0; j<total && i*prime[j]<=MAX; j++)    
  9.         {    
  10.             isPrime[i*prime[j]]=false;    
  11.              if(i%prime[j]==0) break;   
  12.         }    
  13.     }    
  14. }    
 void makePrime2()  
 {  
     memset(isPrime,true,sizeof(isPrime));  
     memset(prime,0,sizeof(prime));  
     for(int i=2;i<=MAX;i++)  
     {  
         if(isPrime[i]) prime[total++]=i; 
         for(int j=0; j<total && i*prime[j]<=MAX; j++)  
         {  
             isPrime[i*prime[j]]=false;  
              if(i%prime[j]==0) break; 
         }  
     }  
 }  

算法中的一个难点是:if(i%prime[j]==0) break;下面做下解释:
先举个例: 4*3=12=6*2;如果没有上面那行代码,则在i=4时,isPrime[12]=false;
在i=6时,isPrime[12]=false;这个句子会执行两次,从而导致重复执行降低了效率。使用上面那行代码进行判断后则可以避免。
注意一个合数和一个质数的乘积可用一个更大的合数和一个更小的质数的乘积表示,如 12=4×3=2×2×3=6×2;4%2=0就表示可以用更大的合数表示4×3,此处退出就可避免重复赋值。

线性筛法(也称为欧拉筛法)是一种高效的素数筛选算法,其时间复杂度为 $O(n)$,能够在线性时间内筛选出 $1$ 到 $n$ 之间的所有素数。该方法的核心思想是通过遍历每个数,并将合数仅被标记一次,从而避免重复筛除,提高效率。 以下是一个使用 C++ 实现线性筛法的示例代码: ```cpp #include <iostream> #include <vector> std::vector<int> linear_sieve(int n) { std::vector<bool> is_prime(n + 1, true); // 用于标记每个数是否为素数 std::vector<int> primes; // 存储素数列表 for (int i = 2; i <= n; ++i) { if (is_prime[i]) { primes.push_back(i); // 如果i是素数,加入素数列表 } // 遍历当前已找到的素数列表 for (size_t j = 0; j < primes.size() && i * primes[j] <= n; ++j) { is_prime[i * primes[j]] = false; // 标记该合数 if (i % primes[j] == 0) { break; // 确保每个合数只被其最小的质因数筛除一次 } } } return primes; // 返回n以内的所有素数 } int main() { int n; std::cout << "请输入一个正整数n:"; std::cin >> n; std::vector<int> primes = linear_sieve(n); std::cout << "1到" << n << "之间的素数有:" << std::endl; for (int prime : primes) { std::cout << prime << " "; } std::cout << std::endl; return 0; } ``` ### 代码说明: 1. **标记数组 `is_prime`**:用于记录每个数是否为素数,初始时设为 `true`。 2. **素数列表 `primes`**:存储筛选出的素数。 3. **外层循环**:从 $2$ 到 $n$ 遍历每个数 $i$。 4. **内层循环**:对于每个素数 $p$,标记 $i \times p$ 为合数;当 $i$ 能被当前素数整除时,停止内层循环以避免重复标记。 5. **输出结果**:将筛选出的素数打印出来。 ### 算法特点: - **高效性**:每个合数只会被其最小的质因数筛除一次,因此时间复杂度为 $O(n)$。 - **空间复杂度**:需要一个大小为 $n+1$ 的布尔数组来标记素数,因此空间复杂度为 $O(n)$。 通过该算法,可以在较短时间内处理大规模的素数筛选问题,适用于对性能要较高的场景。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值