Lylighte
2020-02-01 11:50:50
题意:「查找第
这需要打表生成质数数组(prime[i]
表示第
如下是一般的筛法(埃氏筛):
//生成不大于 n 的所有质数
bool numlist[100000001];
int prime[20000001], cnt;
void work(int n){
for(int i=2; i<=n; i++){
if(numlist[i]==false){
prime[++cnt] = i ;
for(int j=i; i*j<=n; j++)
numlist[i*j] = true;
}
}
return;
}
埃氏筛的思想是:要想得到
有一个小优化,把
当然,埃氏筛效率还是低了些。例如一个数
所以,用这种方法提交,会爆零(我是这样的)。
那么,现在要避免重复筛,要用到另一种筛法:欧拉筛。
先上代码:
bool numlist[100000001];
int prime[20000001], cnt;
void work(int n){
for(int i=2; i<=n; i++){
if(numlist[i]==false)
prime[++cnt] = i ;
for(int j=1; j<=cnt&&i*prime[j]<=n; j++){
numlist[i*prime[j]] = true ;
if(i%prime[j]==0)
break;
}
}
return;
}
避免重复筛,应找到筛合数的一种原则:这个合数只会被它的最大非自身因数(对应最小质因数)筛。这样能保证每个合数只会被筛一次。
(运行过程)从
到了
以此类推,可做出一张表:
质数表 | 筛去的数 | |
---|---|---|
2 | 2 | 4 |
3 | 2, 3 | 6, 9 |
4 | 2, 3 | 8 |
5 | 2, 3, 5 | 10, 15, 25 |
6 | 2, 3, 5 | 12 |
7 | 2, 3, 5, 7 | 14, 21, 28, 35 |
每个质数只被筛一次,复杂度变为
2020/02/01 写完。
2020/02/12 小小的修改。