1 条题解
-
0
题目分析
题目要求我们找出给定区间 ([x_L, x_H]) 内的所有“爆炸性数字”。爆炸性数字的定义为:
- 可以表示为 (x = p_0 \cdot p_1 \cdot p_2 \cdot \ldots \cdot p_n),其中 (p_0 = 1),其余 (p_i) 是不同的质数。
- 存在整数 (A) 和 (B),使得 (p_i = A \cdot p_{i-1} + B)((i = 1, 2, \ldots, n))。
- 序列长度 (n \geq 3)。
解题思路
- 生成质数序列:从 (p_0 = 1) 开始,根据递推关系 (p_i = A \cdot p_{i-1} + B) 生成后续质数。
- 枚举参数:枚举可能的 (A) 和 (B) 的值,生成符合条件的质数序列。
- 检查乘积:计算序列的乘积 (x),并检查是否在给定范围内。
- 去重与统计:确保每个爆炸性数字只被统计一次,并输出结果。
实现步骤
- 质数判断:实现一个高效的质数判断函数
isPrime
。 - 生成序列:对于每个可能的 (A) 和 (B),生成质数序列并检查其乘积是否在范围内。
- 范围检查:确保生成的乘积 (x) 在 ([x_L, x_H]) 内。
- 统计结果:使用集合去重,并统计符合条件的数字数量。
优化思路
- 限制参数范围:(A) 和 (B) 的取值范围不宜过大,否则会导致计算量剧增。
- 提前终止:如果生成的乘积 (x) 超过 (x_H),可以提前终止当前序列的生成。
- 预处理质数:可以预处理一定范围内的质数,加快质数判断速度。
代码实现
#include <iostream> #include <vector> #include <cmath> using namespace std; typedef long long LL; // 判断一个数是否为质数 bool isPrime(LL n) { if (n <= 1) return false; if (n == 2) return true; if (n % 2 == 0) return false; LL max_div = static_cast<LL>(sqrt(n)) + 1; for (LL i = 3; i <= max_div; i += 2) { if (n % i == 0) return false; } return true; } // 计算范围内的爆炸数数量 int countExplosiveNumbers(LL xL, LL xH) { int count = 0; // 枚举可能的初始质数p0 for (LL p0 = 2; p0 <= 1000; ++p0) { if (!isPrime(p0)) continue; // 枚举可能的A值 for (LL A = 1; A <= 100; ++A) { // 生成数列并检查 vector<LL> primes; primes.push_back(p0); LL current = p0; bool valid = true; // 生成最多6个质数的序列 for (int i = 1; i <= 5; ++i) { // 计算B = p1 - A*p0 LL B = primes[1] - A * primes[0]; // 计算下一个质数 LL next = A * current + B; if (next <= current || !isPrime(next)) { valid = false; break; } primes.push_back(next); current = next; // 检查当前乘积是否超出范围 LL product = 1; bool overflow = false; // 使用传统for循环替代范围for循环(C++98不支持) for (vector<LL>::iterator it = primes.begin(); it != primes.end(); ++it) { LL p = *it; if (product > (xH + p - 1) / p) { overflow = true; break; } product *= p; } if (overflow) break; // 检查乘积是否在范围内 if (product >= xL && product <= xH) { ++count; } } } } return count; } int main() { int N; cin >> N; for (int i = 0; i < N; ++i) { LL xL, xH; cin >> xL >> xH; // 处理特殊情况 if (xL > xH) { cout << 0 << endl; continue; } cout << countExplosiveNumbers(xL, xH) << endl; } return 0; }
- 1
信息
- ID
- 2006
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者