1. 问题背景与理解
今天我们来探讨一个有趣的算法问题——"相等序列"。这个问题来自GESP五级考试真题,考察的是质因数分解和贪心算法的应用。题目描述虽然简短,但蕴含着不少值得深入分析的算法思想。
简单来说,我们有一个包含N个正整数的序列,每次操作可以:
- 选择一个数乘以任意质数(花费1金币)
- 选择一个数除以它的一个质因数(花费1金币)
我们的目标是用最少的金币让序列中所有数变得相同。这看似简单,但如何高效计算最小花费呢?
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心思路解析
2.1 质因数分解是关键
要解决这个问题,首先需要理解一个数学事实:两个数相等,当且仅当它们的质因数分解完全相同。这意味着我们需要让所有数的质因数组成及其指数都一致。
例如,考虑数字10(2×5)和6(2×3)。要让它们相等,可以:
- 将6乘以5并除以3(变成2×5)
- 或者将10乘以3并除以5(变成2×3)
2.2 操作代价的计算
每次乘法或除法操作都花费1金币,这与改变的质因数的指数变化量直接相关。如果我们决定将所有数的某个质因数P的指数都调整为k,那么:
- 对于当前指数小于k的数,需要执行(k-current)次乘法
- 对于当前指数大于k的数,需要执行(current-k)次除法
- 对于不包含P的数,需要执行k次乘法(从0开始构建)
我们的目标是找到对每个质因数P的最优k值,使得总操作次数最小。
3. 算法设计与实现
3.1 质因数分解存储
首先,我们需要对每个数进行质因数分解,并记录每个质因数出现的次数:
cpp复制struct PrimeFactor {
vector<int> exponents; // 存储该质因数在各个数中的指数
};
map<int, PrimeFactor> primeFactors; // 质因数到其指数列表的映射
void factorize(int num) {
for(int i=2; i*i<=num; i++) {
int count = 0;
while(num%i == 0) {
num /= i;
count++;
}
if(count > 0) {
