Created by dbywsc.|

dbywsc

园龄:1年3个月粉丝:2关注:0

线性筛素数

学习这个算法的时候看了这位大佬题解

背景

最近遇到一个问题,需要判断大量的数是否是素数,暴力做法会TLE,所以在寻找解决办法的时候了解了欧拉筛法(线性筛法)

代码

这里以洛谷P3383为例

#include <iostream>
#include <cstring>
using namespace std;
bool isPrime[114514191];
int Prime[114514191];
void solve(int n) {
int cnt = 0;
memset(isPrime, true, sizeof(isPrime));
isPrime[1] = false;
for(int i = 2; i <= n; i++) {
if(isPrime[i]) {
Prime[++cnt] = i;
}
for(int j = 1; j <= cnt && i * Prime[j] <= n; j++) {
isPrime[i * Prime[j]] = false;
if(i % Prime[j] == 0) break;
}
}
}
int main(void) {
ios::sync_with_stdio(0);
int n, q;
cin >> n >> q;
solve(n);
while(q--) {
int k;
cin >> k;
cout << Prime[k] << endl;
}
return 0;
}

时间复杂度: O(n)

算法原理

欧拉筛的基本原理是利用因数分解的思想来筛去合数,对于任一合数均可被拆分为×,我们从2开始(因为2本身就素数,所以直接从它开始判断)枚举每一个素数,即Prime[j],那么iPrime[j]必定时一个合数,将其筛去。为了确保线性复杂度,我们期望每一个合数只被它的最小质因数筛去,这样每个数都指挥被筛一遍,为了确保这一点我们使用了if(i % Prime[j] == 0) break;由于j是从小到大开始枚举,当这个条件成立时,Prime[j]必定为i的最小质因数。

正确性证明(出自大佬博客)

设任一要被筛去的合数C的最小质因数为p,令B = C / p,则B的最小质因数一定不小于p×=)所以当外层枚举到枚举i=B时,由于B的最小质因数一定不小于p,所以内层在结束break前一定会遇到p,(博客原话是:所以i在质数枚举至p之前一定不会break),这样就可以保证c会被筛去。

The End

本文作者:dbywsc

本文链接:https://www.cnblogs.com/dbywsc/p/17890872.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   dbywsc  阅读(29)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起