标题被影日收割了
模拟赛题
当一个正整数的质因子个数为质数时,它被称为 “质数中的质数”,现在给出 \(l,r\) ,你需要求出有多少个 “质数中的质数” 在区间 \([l,r]\) 中。
心路历程:
想单纯的记录质数,然后质因数分解(赛后回顾我好像发明了埃式筛)
哦,只能得10分
打表
浪费了很多时间,最后用不超过文件大小限制的代码得了 40 分
普遍的 80 分 :
线性筛扫一边 \(1-r\) 的质数,质因数分解时 , 记录分解过的数的质因子个数
线性筛 :
void Prime(int n){
memset(isprime,1,sizeof(isprime));
isprime[1]=0;
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]]=0;
if(i%prime[j]==0)break;
}
}
}
100分 :
每次枚举质数 \(p\) , 在 \(l-r\) 中找到第一个 \(p\) 的倍数的位置 , 每次跳 \(p\) , 统计质因子的个数 , 顺便做一下埃式筛
复杂度 \((r-l)log(r-l)\)
#include <bits/stdc++.h>
using namespace std;
const int N=31622;
int ys[1000006],cnt[1000006];
bool vis[N+2];
int main(){
int l,r;
cin>>l>>r;
for(int i=l;i<=r;i++){
ys[i-l]=i;
}
vis[0]=1;
vis[1]=1;
for(int i=2;i<=N;i++){
if(!vis[i]){
for(int j=(l+i-1)/i*i;j<=r;j+=i){
int k=ys[j-l];
while(k%i==0){
cnt[j-l]++;
k/=i;
}
ys[j-l]=k;
}
}
for(int p=i*2;p<=N;p+=i)vis[p]=1;
}
int ans=0;
for(int i=l;i<=r;i++){
if(ys[i-l]!=1)cnt[i-l]++;
if(!vis[cnt[i-l]])ans++;
}
cout<<ans;
return 0;
}
有一道题是一个套路
素数密度
给定 \(L,R\) ,请计算区间 \([L,R]\) 中素数的个数。
\(1<=L<=R<2^{31} , R-L<=10^6\)
\(R\) 太大 , 但 \(R-L\) 很小 ,
先筛出 \(1-\sqrt{R}\) 的质数 , 再用他们把 \(L-R\) 的合数筛出来
为什么是 \(1-\sqrt{R}\) ?
假设 $n=a*b , a<=b , a $ 为质数
就完了