xtuoj Prime Twins

题目

思路

解题思路

1. 问题分析
  • 核心需求:给定多组查询区间 [a, b],统计区间内孪生素数对(即两个素数相差 2,如 (3,5)、(5,7))的数量。
  • 关键:孪生素数对的形式是 (x, x+2),因此统计的本质是找满足 a ≤ x ≤ b-2xx+2 都是素数的 x 的个数。
2. 核心难点与解决思路
  • 难点:如果对每个查询都逐个判断数是否为素数,时间复杂度会很高(尤其是数据范围到 500 万),无法高效处理多组查询。
  • 解决思路:预处理 + 前缀和 (空间换时间):
    1. 先用筛法一次性找出所有素数(预处理);
    2. 再用前缀和数组记录前 i 个数中孪生素数对的总数;
    3. 每个查询直接通过前缀和数组的差值快速得到结果。
3. 具体实现步骤
步骤 1:素数筛选(埃拉托斯特尼筛法)
  • 目的:标记出 500 万以内所有非素数,为后续判断孪生素数做准备。
  • 操作:
    • 定义布尔数组 st[N+1]st[i] = true 表示 i 不是素数,初始全为 false
    • 遍历 i 从 2 到 N:若 i 未被标记(是素数),则标记 i 的所有倍数(从 i*i 开始)为非素数。
步骤 2:孪生素数判断
  • 目的:判断一个数 x 是否是某对孪生素数的较小数(即 x 和 x+2 都是素数)。
  • 操作:
    • 检查条件:x ≤ N-2(保证 x+2 不超范围)、!st[x](x 是素数)、!st[x+2](x+2 是素数)。
步骤 3:前缀和数组构建
  • 目的:构建数组 f[N+1],其中 f[i] 表示 2~i 范围内孪生素数对的总数。
  • 操作:
    • 初始化 f[0] = f[1] = 0(小于 2 无素数);
    • 遍历 i 从 2 到 N:
      • 若 i 是孪生素数对的较小数,f[i] = f[i-1] + 1
      • 否则,f[i] = f[i-1](总数不变)。
步骤 4:查询处理
  • 目的:对每组查询 [a, b],快速计算结果。
  • 操作:
    • 边界处理:若 a > b-2b ≤ 3,结果为 0(无符合条件的孪生素数对);
    • 正常情况:结果 = f[b-2] - f[a-1](前缀和差值,即区间 [a, b-2] 内的孪生素数对数量)。
4. 主函数流程
  • 先执行素数筛选和前缀和数组构建(仅执行一次);
  • 读入查询次数 K,循环处理每组查询,调用查询逻辑并输出结果。

总结

  1. 核心思想:用筛法预处理素数 + 前缀和快速查询,将多次查询的时间复杂度从 O (n) 降为 O(1);
  2. 关键逻辑:孪生素数对 (x, x+2) 的统计转化为对 x 的范围判断,再通过前缀和差值计算区间数量;
  3. 效率优势:预处理仅需 O (N log log N) 时间,后续每个查询都是 O (1),适合大数据范围和多组查询场景。

代码

cpp 复制代码
#include<stdio.h>
#include<stdbool.h>
#define ll long long

#define N 5000000

int cnt=0,ans,f[N+1];
bool st[N+1]={false};

void sieve(){
	ll i,j;
	for(i=2;i<=N;i++){
		if(st[i]) continue;
		for(j=i*i;j<=N;j+=i)
			st[j]=true;
	}
}

bool check(int x){
	return (x<=N-2)&&(!st[x])&&(!st[x+2]);
}

void prefix(){
	f[0]=f[1]=0;
	int i;
	for(i=2;i<=N;i++){
		if(check(i)) f[i]=f[i-1]+1;
		else f[i]=f[i-1];
	}
}

void solves(int a,int b){
	if(a>b-2||b<=3) ans=0;
	else ans=f[b-2]-f[a-1];
	printf("%d\n",ans);
}

int main(){
	sieve();
	prefix();
	int K,a,b;
	scanf("%d",&K);
	while(K--){
		scanf("%d%d",&a,&b);
		solves(a,b);
	}
}
相关推荐
历程里程碑18 分钟前
LeetCode热题11:盛水容器双指针妙解
c语言·数据结构·c++·经验分享·算法·leetcode·职场和发展
wadesir7 小时前
Rust中的条件变量详解(使用Condvar的wait方法实现线程同步)
开发语言·算法·rust
yugi9878387 小时前
基于MATLAB实现协同过滤电影推荐系统
算法·matlab
TimberWill7 小时前
哈希-02-最长连续序列
算法·leetcode·排序算法
Morwit8 小时前
【力扣hot100】64. 最小路径和
c++·算法·leetcode
leoufung8 小时前
LeetCode 373. Find K Pairs with Smallest Sums:从暴力到堆优化的完整思路与踩坑
java·算法·leetcode
wifi chicken8 小时前
数组遍历求值,行遍历和列遍历谁更快
c语言·数据结构·算法
胡楚昊9 小时前
NSSCTF动调题包通关
开发语言·javascript·算法
Gold_Dino9 小时前
agc011_e 题解
算法
bubiyoushang8889 小时前
基于蚁群算法的直流电机PID参数整定 MATLAB 实现
数据结构·算法·matlab