题目
题目描述
小红定义一个数满足以下条件为“漂亮数”:
-
该数不是素数。
-
该数可以分解为2个素数的乘积。
4 是漂亮数,因为 4=2*2
21 是漂亮数,因为 21=3*7
30 不是漂亮数,因为 30=235
73 不是漂亮数。因为 73 本身即是素数。
输入 \(l\) 和 \(r\) ,请你输出 \([l,r]\) 闭区间中有多少个漂亮数。
输入描述
第一行输入一个正整数 \(t\) ,代表有 \(t\) 次询问
两个正整数 \(l\) 和 \(r\) ,用空格隔开。
\(1 \leq t \leq 10^5\)
\(1 \leq l \leq r \leq 10^8\)
输出描述
共输出 \(t\) 行,每行为一个整数,代表 \(l\) 到 \(r\) 中漂亮数的数量。
示例1
输入
1
150 200
输出
12
题解
知识点:筛法,前缀和。
我们可以考虑线性筛的过程中,判断一个数是否是由一个素数 \(i\) 的素数倍 \(j\) 筛掉的,此时 \(j\) 是最小质因子,\(i\) 是另一个质因子,于是这个数就是符合条件的数。
最后,我们用前缀和维护一下询问即可。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e8 + 7;
bool vis[N];
int f[N];
vector<int> prime;
void get_prime(int n) {
for (int i = 2;i <= n;i++) {
if (!vis[i]) prime.push_back(i);
for (auto j : prime) {
if (i * j > n) break;
vis[i * j] = 1;
if (!vis[i]) f[i * j] = 1;
if (!(i % j)) break;
}
}
}
bool solve() {
int l, r;
cin >> l >> r;
cout << f[r] - f[l - 1] << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
get_prime(1e8);
for (int i = 1;i <= 1e8;i++) f[i] += f[i - 1];
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}
标签:prime,vis,int,漂亮,leq,素数,NC224933
From: https://www.cnblogs.com/BlankYang/p/17657128.html