【2025年莆田市第五期C++专项第三轮选拔真题(初中组)】特殊合数
特殊合数
给你一个整数 n
,请你找出并返回第 n
个 特殊合数 。
特殊合数 就是质因子只包含 2
、3
和 5
的正整数。
声明:在本题中,1
也视为特殊合数。
输入
输入一个整数n
输出
输出第n
个 特殊合数
输入样例1
10
输出样例1
12
输入样例2
1
输出样例2
1
样例解释
样例1:
输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个特殊合数组成的序列。
样例2:
输入:n = 1
输出:1
解释:1 通常被视为特殊合数。
数据范围:
20 % 20 \% 20%的数据: 1 ≤ n ≤ 100 1 \leq n \leq 100 1≤n≤100
40 % 40 \% 40%的数据: 1 ≤ n ≤ 1000 1 \leq n \leq 1000 1≤n≤1000
100 % 100 \% 100%的数据: 1 ≤ n ≤ 10000 1 \leq n \leq 10000 1≤n≤10000
问题描述
给定一个整数n,找出并返回第n个特殊合数。特殊合数是指质因子只包含2、3和5的正整数,其中1也被视为特殊合数。
解题思路
这个问题可以使用动态规划的方法高效解决,类似于经典的"丑数"问题。基本思想是:
- 初始化一个数组,第一个元素为1
- 维护三个指针,分别表示乘以2、3和5后可能产生下一个特殊合数的位置
- 每次选择三个指针指向的数乘以对应因子后的最小值作为下一个特殊合数
- 如果某个指针产生的数被选中,则该指针后移一位
这种方法确保了我们可以按顺序生成所有特殊合数,而不会遗漏任何数字。
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
vector<long long> specialNumbers(n);
specialNumbers[0] = 1; // 第一个特殊合数是1
int index2 = 0, index3 = 0, index5 = 0; // 分别表示乘以2、3、5的指针
for (int i = 1; i < n; ++i) {
// 计算下一个可能的特殊合数
long long nextBy2 = specialNumbers[index2] * 2;
long long nextBy3 = specialNumbers[index3] * 3;
long long nextBy5 = specialNumbers[index5] * 5;
// 选择最小的作为下一个特殊合数
long long nextNumber = min({nextBy2, nextBy3, nextBy5});
specialNumbers[i] = nextNumber;
// 移动产生当前最小值的指针
if (nextNumber == nextBy2) ++index2;
if (nextNumber == nextBy3) ++index3;
if (nextNumber == nextBy5) ++index5;
}
cout << specialNumbers[n - 1] << endl;
return 0;
}
复杂度分析
时间复杂度:O(n),我们只需要进行n次循环即可找到第n个特殊合数
空间复杂度:O(n),需要存储前n个特殊合数