#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
vector<long long> generate(long long n) {
vector<bool> is(n + 1, true);// 标记是否为素数,初始值全为 true
vector<long long> v;
is[0] = is[1] = false; // 0 和 1 不是素数
for (long long i = 2; i <= n; i++) {
if (is[i]) {
v.push_back(i); // 如果当前数是素数,存入结果数组
for (long long j = i * i; j <= n; j += i) {
is[j] = false; // 将当前素数的倍数标记为非素数
}
}
}
return v;
}
int main() {
int a = 2333;
long long b = 23333333333333;
long long n = sqrt(b);
vector<long long> v = generate(n); // 生成所有小于等于 sqrt(b) 的素数
long long ans = 0;
for (int i = 0; i < v.size(); i++) {
long long p = v[i];
long long p2 = p * p; // p 的平方,提前计算以减少重复计算
for (int j = i + 1; j < v.size(); j++) {
long long q = v[j];
long long q2 = q * q;
if (p > b / q2) break; // 提前判断是否溢出,避免计算 p^2 * q^2 导致超出 long long 范围
long long x = p2 * q2;
if (x >= a && x <= b) {// 检查是否在区间范围内,满足条件则计入答案
ans++;
}
}
}
cout << ans;
return 0;
}
long long j = i * i; j <= n; j += i
,
目的是在使用埃拉托色尼筛法时将素数 i 的所有倍数标记为非素数。
在筛法中,素数 i 的所有倍数可以从 i^2 开始筛除。因为对于所有小于 i^2 的倍数 i×k(其中 k<i),这些倍数在之前的迭代中已经被标记为非素数。
j += i
:这步是使得从 i^2 开始的每个 i 的倍数都被标记为非素数。每次加上 i,这样可以确保我们遍历到的所有倍数是 i 的倍数。
提前计算 q² > b / p² 来避免乘法溢出。也就是b < q² * p² 的情况break