P1865 A % B Problem (素数筛法,前缀和)

本文介绍了一种改进的素数筛法,用于快速计算指定区间内的质数个数。通过记录每个数之前的质数数量,可以高效地解决区间质数计数问题,并提供了完整的AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

区间质数个数

输入输出格式

输入格式:

 

一行两个整数 询问次数n,范围m

接下来n行,每行两个整数 l,r 表示区间

 

输出格式:

 

对于每次询问输出个数 t,如l或r∉[1,m]输出 Crossing the line

 

输入输出样例

输入样例#1: 复制

2 5
1 3
2 6

输出样例#1: 复制

2
Crossing the line

说明

【数据范围和约定】

对于20%的数据 1<=n<=10 1<=m<=10

对于100%的数据 1<=n<=1000 1<=m<=1000000 -10^9<=l<=r<=10^9 1<=t<=1000000

第一眼肯定会想到素数筛法,但还需将此算法进行改进。

如果每一次记录当前这个数之前有几个是素数,则再求某一区间内的素数个数就变得极为容易。(注意:在求区间[L,  R]内的素数个数时,不能直接用num[R] - num[L],显然这样减少一个计算了一个数。

例如:计算区间[2, 8]内的素数个数,

           数字:1  2  3  4  5  6  7  8  9  10

       前缀和:0  1  2  2  3  3  4   4  4  4 

num[8] - num[2] = 4 - 1 = 3,显然是错的,所以应该减去他的前一个数的前缀和,即num[R] - num[L-1]

 

素数筛法模板(加计数素数前缀和)

void init(){
	memset(notprime, false, sizeof(notprime));
	memset(num, 0, sizeof(num));
	notprime[0] = notprime[1] = true;
	num[0] = 0; num[1] = 0;
	for(int i = 2; i < maxn; i++){
		if(!notprime[i]){
			num[i] = num[i-1] + 1;
			if(i > maxn/i) continue;
			for(int j = i*i; j < maxn; j += i)
				notprime[j] = true;
		}
		else num[i] = num[i-1];
	}
}

 

 

ac代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>

using namespace std;
typedef long long LL;
const int maxn = 1e6+5;

bool notprime[maxn];
int num[maxn];

int n, m;
int l, r;

void init(){
	memset(notprime, false, sizeof(notprime));
	memset(num, 0, sizeof(num));
	notprime[0] = notprime[1] = true;
	num[0] = 0; num[1] = 0;
	for(int i = 2; i < maxn; i++){
		if(!notprime[i]){
			num[i] = num[i-1] + 1;
			if(i > maxn/i) continue;
			for(int j = i*i; j < maxn; j += i)
				notprime[j] = true;
		}
		else num[i] = num[i-1];
	}
}

int main()
{
	init();
	scanf("%d%d", &n, &m);
	while(n--){
		scanf("%d%d", &l, &r);
		if(l < 1||r > m) printf("Crossing the line\n");
		else printf("%d\n", num[r] - num[l-1]);
	}
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值