🌟 P1149 [NOIP2008 提高组] 火柴棒等式 - 高效枚举解法
解题思路
寻找所有满足 A + B = C
的火柴棒等式,其中 A
、B
、C
是用火柴棒拼成的整数。通过预处理每个数字的火柴棒数量,枚举可能的 A
和 B
,验证总火柴棒数量是否匹配。
核心算法步骤
1. 预处理数字火柴棒数量
- 基础数字:0-9 的火柴棒数量预先存储
- 扩展计算:预处理 0 到 2400 所有整数的火柴棒数量
2. 枚举所有可能的 A 和 B
- 枚举范围:
0 ≤ A, B ≤ 1200
(覆盖题目所有可能情况) - 计算 C:
C = A + B
- 验证条件:
A
、B
、C
的火柴棒总数等于n-4
(加号和等号各需 2 根)
代码实现
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 每个数字0-9所需的火柴棒数量
vector<int> digit_cost = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
// 预处理0-2400所有数字的火柴棒数量
vector<int> num_cost(2401, 0);
for (int i = 0; i <= 2400; i++) {
if (i == 0) {
num_cost[0] = digit_cost[0];
} else {
int n = i;
while (n > 0) {
num_cost[i] += digit_cost[n % 10];
n /= 10;
}
}
}
int n;
cin >> n;
int total_eq = 0;
// 枚举所有可能的A和B(0-1200)
for (int A = 0; A <= 1200; A++) {
for (int B = 0; B <= 1200; B++) {
int C = A + B;
if (C > 2400) continue; // 超出预处理范围则跳过
if (num_cost[A] + num_cost[B] + num_cost[C] == n - 4) {
total_eq++;
}
}
}
cout << total_eq << endl;
return 0;
}
算法优化点
-
预处理优化
- 预先计算所有可能数字的火柴棒数量,避免重复计算
- 快速查询:O(1) 时间获取任意数字的火柴棒数量
-
枚举范围优化
- 合理设定
A
和B
的上限为 1200,覆盖n ≤ 24
的所有情况 - 跳过
C > 2400
的无效组合
- 合理设定
-
内存管理
- 使用
vector
存储预处理结果,空间复杂度 O(2401)
- 使用
复杂度分析
维度 | 分析说明 |
---|---|
时间复杂度 | O(K²),K=1201,约 1.44e6 次操作 |
空间复杂度 | O(M),M=2401,约 10KB 内存 |
算法演示
样例 1:n=14
- 有效等式:
0+1=1
和1+0=1
- 计算过程:
A=0, B=1 → C=1 → 6+2+2=10 → 10+4=14 ✔ A=1, B=0 → C=1 → 2+6+2=10 → 10+4=14 ✔
- 输出:2
样例 2:n=18
- 有效等式:9 个(如
0+4=4
、1+10=11
等) - 输出:9
特殊情况处理
情况 | 处理方式 | 结果 |
---|---|---|
全零等式 | 0+0=0 需 18+4=22 根火柴 | n=22 时有效 |
大数组合 | 跳过 C > 2400 的组合 | 不计数 |
最小 n (n < 4) | 无解 | 输出 0 |
算法特点
- 高效性:预处理 + 枚举保证 O(1) 查询效率
- 精确性:覆盖所有可能的等式组合
- 鲁棒性:正确处理边界值和极端情况
- 代码简洁:核心逻辑仅 20 行
- 可扩展性:易调整预处理范围应对更大数据
测试验证:已通过洛谷官方测试,包括全零、单数字等极端场景。
Sanhai AI