🌟《素数筛法10道经典训练题》
第一题:输出1~n所有素数(埃氏筛基础题)
1、🏰故事
素数王国要发布一份 素数名单。
(1)输入一个数字 n,请输出:
1~n 所有素数
(2)输入
30
(3)输出
2 3 5 7 11 13 17 19 23 29
2、思路
(1)使用 埃氏筛
(2)步骤:
1 初始化全部为素数
2 从2开始
3 删除倍数
3、参考代码
#include <iostream>
using namespace std;
const int N = 1000000;
bool isPrime[N];
int main()
{
int n;
cin>>n;
for(int i=2;i<=n;i++)
isPrime[i]=true;
for(int i=2;i*i<=n;i++)
{
if(isPrime[i])
{
for(int j=i*i;j<=n;j+=i)
isPrime[j]=false;
}
}
for(int i=2;i<=n;i++)
if(isPrime[i])
cout<<i<<" ";
}
第二题:统计素数个数
1、🏰故事
(1)国王想知道:
1~n 一共有多少个素数
(2)输入
20
(3)输出
8
(4)因为
2 3 5 7 11 13 17 19
数一数,一共是8个
2、思路
先 筛素数
再 统计数量
3、参考代码
#include <iostream>
using namespace std;
const int N = 1000000;
bool isPrime[N];
int main()
{
int n;
cin>>n;
for(int i=2;i<=n;i++)
isPrime[i]=true;
for(int i=2;i*i<=n;i++)
if(isPrime[i])
for(int j=i*i;j<=n;j+=i)
isPrime[j]=false;
int cnt=0;
for(int i=2;i<=n;i++)
if(isPrime[i])
cnt++;
cout<<cnt;
}
第三题:判断多个数字是否为素数
1、🏰故事
(1)城门守卫需要检查很多数字。
输入 t个数字,判断每个是不是素数。
(2)输入
5
2 4 7 9 11
(3)输出
Yes
No
Yes
No
Yes
2、思路
先筛到 最大值
再查询。
3、参考代码
#include <iostream>
using namespace std;
const int N=1000000;
bool isPrime[N];
int main()
{
int t;
cin>>t;
int a[1000];
int mx=0;
for(int i=0;i<t;i++)
{
cin>>a[i];
mx=max(mx,a[i]);
}
for(int i=2;i<=mx;i++)
isPrime[i]=true;
for(int i=2;i*i<=mx;i++)
if(isPrime[i])
for(int j=i*i;j<=mx;j+=i)
isPrime[j]=false;
for(int i=0;i<t;i++)
{
if(isPrime[a[i]])
cout<<"Yes\n";
else
cout<<"No\n";
}
}
第四题:输出第k个素数(线性筛)
1、🏰故事
数学家问:
第1000个素数是多少?
2、思路
使用 线性筛
记录素数数组。
3、参考代码
#include <iostream>
using namespace std;
const int N=1000000;
int prime[N];
bool vis[N];
int main()
{
int n;
cin>>n;
int cnt=0;
for(int i=2;i<N;i++)
{
if(!vis[i])
prime[cnt++]=i;
for(int j=0;j<cnt && i*prime[j]<N;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
break;
}
if(cnt>=n)
break;
}
cout<<prime[n-1];
}
第五题:求1~n所有素数的和
1、🏰故事
(1)数学家问:
1~n所有素数的和是多少?
(2)输入
10
(2)输出
17
(3)因为
2+3+5+7=17
2、参考代码
#include <iostream>
using namespace std;
const int N=1000000;
bool isPrime[N];
int main()
{
int n;
cin>>n;
for(int i=2;i<=n;i++)
isPrime[i]=true;
for(int i=2;i*i<=n;i++)
if(isPrime[i])
for(int j=i*i;j<=n;j+=i)
isPrime[j]=false;
long long sum=0;
for(int i=2;i<=n;i++)
if(isPrime[i])
sum+=i;
cout<<sum;
}
第六题:输出区间内素数
1、🏰故事
(1)数学家问:
输入一个区间,输出区间内的所有素数。
(2)输入:
L R
(3)输出
L~R 的所有素数
2、输入
10 30
输出
11 13 17 19 23 29
3、思路
筛到 R
4、参考代码
#include <iostream>
using namespace std;
const int N=1000000;
bool isPrime[N];
int main()
{
int L,R;
cin>>L>>R;
for(int i=2;i<=R;i++)
isPrime[i]=true;
for(int i=2;i*i<=R;i++)
if(isPrime[i])
for(int j=i*i;j<=R;j+=i)
isPrime[j]=false;
for(int i=L;i<=R;i++)
if(isPrime[i])
cout<<i<<" ";
}
第七题:统计区间素数数量
1、🏰故事
(1)数学家问:
输入一个区间,输出区间内的所有素数的数量。
(2)输入
L R
(3)输出
区间素数数量
2、参考代码
#include <iostream>
using namespace std;
const int N=1000000;
bool isPrime[N];
int main()
{
int L,R;
cin>>L>>R;
for(int i=2;i<=R;i++)
isPrime[i]=true;
for(int i=2;i*i<=R;i++)
if(isPrime[i])
for(int j=i*i;j<=R;j+=i)
isPrime[j]=false;
int cnt=0;
for(int i=L;i<=R;i++)
if(isPrime[i])
cnt++;
cout<<cnt;
}
第八题:输出前n个素数(线性筛)
1、🏰故事
(1)数学家问:
输入数字n,输出从第一个到第n个素数。
(2)输入
10
(3)输出
2 3 5 7 11 13 17 19 23 29
2、参考代码
#include <iostream>
using namespace std;
const int N=1000000;
int prime[N];
bool vis[N];
int main()
{
int n;
cin>>n;
int cnt=0;
for(int i=2;i<N;i++)
{
if(!vis[i])
prime[cnt++]=i;
for(int j=0;j<cnt && i*prime[j]<N;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
break;
}
if(cnt>=n)
break;
}
for(int i=0;i<n;i++)
cout<<prime[i]<<" ";
}
第九题:判断哥德巴赫猜想
1、🏰故事
(1)数学家问:
输入任意大于2的偶数,将它分为两个素数的和
(2)输入:
n (偶数)
(3)找两个素数:
p + q = n
(4)输入
20
(5)输出
3 17
2、参考代码
#include <iostream>
using namespace std;
const int N=1000000;
bool isPrime[N];
int main()
{
int n;
cin>>n;
for(int i=2;i<=n;i++)
isPrime[i]=true;
for(int i=2;i*i<=n;i++)
if(isPrime[i])
for(int j=i*i;j<=n;j+=i)
isPrime[j]=false;
for(int i=2;i<=n;i++)
{
if(isPrime[i] && isPrime[n-i])
{
cout<<i<<" "<<n-i;
break;
}
}
}
第十题:统计每个数的最小质因数(线性筛进阶)
1、🏰故事
(1)数学家问:
给你一个数字n,输出从2~n它的最小因数
这题是 线性筛的优势题。
(2)输入
10
(3)输出
2:2
3:3
4:2
5:5
6:2
7:7
8:2
9:3
10:2
2、参考代码
#include <iostream>
using namespace std;
const int N=1000000;
int prime[N];
int minp[N];
bool vis[N];
int main()
{
int n;
cin>>n;
int cnt=0;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
prime[cnt++]=i;
minp[i]=i;
}
for(int j=0;j<cnt && i*prime[j]<=n;j++)
{
vis[i*prime[j]]=true;
minp[i*prime[j]]=prime[j];
if(i%prime[j]==0)
break;
}
}
for(int i=2;i<=n;i++)
cout<<i<<":"<<minp[i]<<endl;
}
🌟10题知识总结
| 题目 | 使用筛法 |
|---|---|
| 输出素数 | 埃氏筛 |
| 统计素数 | 埃氏筛 |
| 多次查询 | 埃氏筛 |
| 第k个素数 | 线性筛 |
| 素数求和 | 埃氏筛 |
| 区间素数 | 埃氏筛 |
| 区间统计 | 埃氏筛 |
| 前n素数 | 线性筛 |
| 哥德巴赫 | 埃氏筛 |
| 最小质因数 | 线性筛 |
🎯 最重要经验
比赛中:
1、埃氏筛
适合:
快速得到所有素数
2、线性筛
适合:
记录素数表
记录最小质因数
复杂数论
