切入点的分析 - 2019.11.13 素数统计
Posted lrw04
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了切入点的分析 - 2019.11.13 素数统计相关的知识,希望对你有一定的参考价值。
题面
【问题描述】
小 tan 的老师揣谙戈给同学们布置了一道题,要求统计给定区间内素数的个数。“这不是很简单吗?”小 tan 忍不住说。揣谙戈冷笑 一下说:“等你们看到题目就知道了。”便转身离去。
果然,小 tan 被那极大的区间吓怕了,现在是你拯救她的时候。
【输入】
输入文件名为 pcount.in
。
输入一行两个正整数 (a) 和 (b),表示给定区间为 ([a,b])。
【输出】
输出文件名为 pcount.out
。 输出一个整数,表示区间内素数数量。
【输入输出样例】
pcount.in
1 17
pcount.out
7
【数据范围】
对于 (30\%) 的数据,有 (n<mle1000);
对于 (60\%) 的数据,有 (n<mle1000000);
对于 (100\%) 的数据,有 (n<m<2^{31}),(m-nle1000000)。
解
对于每个合数 (c),必然存在一个 (p) 使得 (p|c) 且 (plesqrt{c}).
想要筛 ([L,R]) 中的素数,瓶颈在于 (R). 有了这个结论,可以只筛 ([1,sqrt{R}]) 的素数,并用这些素数筛 ([L,R]) 中的数。
程序
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MAX_SQRT 66000
#define MAXN 1000000
#define MAXL 1000050
ll a, b, ps[MAXN];
bool isp[MAX_SQRT], ispr[MAXL];
int pt = 0;
void filt() {
isp[1] = false;
for (ll i = 2; i * i <= b; i++)
isp[i] = true;
for (ll i = 1; i * i <= b; i++) {
// cout << i << endl;
if (!isp[i]) continue;
// cout << i << endl;
ps[pt++] = i;
for (ll j = i * i; j * j <= b; j += i)
isp[j] = false;
}
}
void isprset(ll i, bool v) {
ispr[i - a] = v;
}
bool isprget(ll i) {
return ispr[i - a];
}
int main() {
// freopen("pcount.in", "r", stdin);
// freopen("pcount.out", "w", stdout);
cin >> a >> b;
filt();
// cout << "here" << endl;
// for (int i = 0; i < pt; i++) cout << ps[i] << " ";
// cout << endl;
for (ll i = a; i <= b; i++)
isprset(i, true);
for (int i = 0; i < pt; i++) {
int p = ps[i];
for (ll j = max(a / p * p, 2ll * p); j <= b; j += p) {
isprset(j, false);
}
}
int ans = 0;
for (ll i = max(a, 2ll); i <= b; i++)
if (isprget(i)) {
ans++;
// cout << i << endl;
}
cout << ans << endl;
return 0;
}
以上是关于切入点的分析 - 2019.11.13 素数统计的主要内容,如果未能解决你的问题,请参考以下文章