标题被影日收割了

模拟赛题

当一个正整数的质因子个数为质数时,它被称为 “质数中的质数”,现在给出 \(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 $ 为质数
就完了

posted @ 2024-09-08 19:49  小惰惰  阅读(6)  评论(0编辑  收藏  举报
/* 鼠标点击求赞文字特效 */