前缀知识:埃氏筛法
核心:从2开始删去素数本身倍数,向后找到的第一个数字一定是素数。
图解:
模板代码
#include<bits/stdc++.h>
using namespace std;
int d[100000001];
int main()
{
int n;
scanf("%d",&n);
for(int i=2;i<=n;i++)
if(d[i]==0)
{
for(int j=2;i*j<=n;j++)
d[i*j]=1;
printf("%d ",i);
}
return 0;
}
#A. 不可整除
- 传统题1000ms256MiB
Description
给你N个数字,用a1,a2,a3.....an来代表
请找出这样的ai,其满足对于所有的j
当j!=i时,ai % aj均不为0
请统计这样的元素的个数
Format
Input
第一行给出数字N
第二行给出N个数字,权值小于等于1e6
N<=2e5
Output
如题
Samples
输入数据 1
5
24 11 8 3 16
输出数据 1
3
输入数据 2
4
5 5 5 5
输出数据 2
0
输入数据 3
10
33 18 45 28 8 19 89 86 2 4
输出数据 3
5
Hint
对于样例1
有3个数字满足条件,分别为11,8,3
对于样例3
有5个数字满足条件2,19,33,45,89
把输入数字翻倍,标记出现数字,若某输入的数字出现次数为0,则说明其他的数都不是这个数的因数,即为所求。
#include<bits/stdc++.h>
using namespace std;
int n,d[200003],ans,sum[1000003],mx;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&d[i]);
mx=max(mx,d[i]);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=mx/d[i];j++)
sum[d[i]*j]++;
for(int i=1;i<=n;i++)
if(sum[d[i]]==1)
ans++;
printf("%d",ans);
return 0;
}
#B. 区间内的质数
- 传统题1000ms256MiB
Description
请找出区间[L,R]中所有的质数
Format
Input
每行输入两个整数L和U,其中L和U的差值不会超过1000000
1≤L<U≤2^31−1
Output
从小到大,每行输出一个质数
Samples
输入数据 1
2 5
输出数据 1
2
3
5
输入数据 2
2147483587 2147483647
输出数据 2
2147483587
2147483629
2147483647
筛出2-sqrt(r)间的质数,就可推出l-r的所有质数。
l--r开不下数组,但差值很小,平移至0--r-l。
#include<bits/stdc++.h>
using namespace std;
int l,r,prime[3000000],tot,ans[1000002],len,op;
bool num[3000000];
int main()
{
scanf("%d%d",&l,&r);
if(l==1)//!注意!否则1也会被标记为质数
l++;
memset(num,true,sizeof(num));
for(int i=2;i<=sqrt(r);i++)//筛出2-sqrt(r)内的质数
if(num[i]==true)
{
tot++;
prime[tot]=i;
for(int j=2;j<=sqrt(r)/i;j++)
num[i*j]=false;
}
for(int i=1;i<=tot;i++)
{
len=l/prime[i];
if(l%prime[i]!=0)
len++;
for(int j=len;j<=r/prime[i];j++)
if(j!=1)//j=1,j*prime[i]=prime[i]为质数
ans[j*prime[i]-l]=1;//数组平移
}
for(int i=0;i<=r-l;i++)
if(ans[i]==0)
printf("%d\n",i+l);
return 0;
}