优化代码解决组合数计算超时问题
### 📝问题分析 原代码超时(TLE)的主要原因在于每次调用 `factorial` 函数计算阶乘时,时间复杂度较高,并且每次计算组合数都重复计算阶乘,导致整体时间复杂度增加。可以通过预处理阶乘和阶乘的逆元来优化,避免重复计算。 ### 💻优化后的代码 ```cpp #include <iostream> using namespace std; const int MOD = 1e9 + 7; const int MAXN = 1000005; // 假设最大值不超过1000000 // 预处理阶乘和阶乘的逆元 long long fact[MAXN], inv_fact[MAXN]; // 快速幂计算 a^b % MOD long long fast_pow(long long a, long long b) { long long res = 1; while (b > 0) { if (b & 1) { res = (res * a) % MOD; } a = (a * a) % MOD; b >>= 1; } return res; } // 预处理阶乘和阶乘的逆元 void preprocess(int n) { fact[0] = 1; for (int i = 1; i <= n; i++) { fact[i] = (fact[i - 1] * i) % MOD; } inv_fact[n] = fast_pow(fact[n], MOD - 2); for (int i = n - 1; i >= 0; i--) { inv_fact[i] = (inv_fact[i + 1] * (i + 1)) % MOD; } } // 计算组合数 C(n, k) long long combination(long long n, long long k) { if (k > n) return 0; return (fact[n] * inv_fact[k] % MOD * inv_fact[n - k]) % MOD; } int main() { int n, m; cin >> n >> m; long long ans = 1; long long total = n * m; // 预处理阶乘和阶乘的逆元 preprocess(total); for (int i = 0; i < n; i++) { ans = (ans * combination(total, m)) % MOD; total -= m; } cout << ans << endl; return 0; } ``` ### 💡代码解释 1. **预处理阶乘和阶乘的逆元**:通过 `preprocess` 函数,预先计算出从 `0` 到 `total` 的阶乘和阶乘的逆元,避免在计算组合数时重复计算阶乘。 2. **快速幂计算逆元**:使用 `fast_pow` 函数计算阶乘的逆元,时间复杂度为 $O(log MOD)$。 3. **计算组合数**:通过预处理的阶乘和阶乘的逆元,直接计算组合数,时间复杂度为 $O(1)$。 ### ⏱️复杂度分析 - **时间复杂度**:预处理阶乘和阶乘的逆元的时间复杂度为 $O(total)$,计算组合数的时间复杂度为 $O(n)$,因此总的时间复杂度为 $O(total + n)$。 - **空间复杂度**:主要用于存储阶乘和阶乘的逆元,空间复杂度为 $O(total)$。 ######[AI问答 | 810点数解答 | 2026-05-31 15:28:14]
- C3期末:精准求解 3 - 20 范围内数列第 k 项值及注意要点(字节豆包 | 242点数解答 | 2025-06-15 11:26:19)171
- C++求解:查找3 - 20项数列第k项值及注意要点(字节豆包 | 325点数解答 | 2025-06-15 11:27:11)195
- 解析React 15与Vue 2:从O(n^3)到O(n),Diff算法时间复杂度计算及性能对比 (阿里通义 | 379点数解答 | 2023-11-09 01:49:19)367
- 缜密逻辑,全新无名杀“风餐”技能代码精心打造与深度解析 (字节豆包 | 469点数解答 | 2025-04-05 11:37:06)292
- 精准优化:明确需求,开启高效提升之旅! (字节豆包 | 52点数解答 | 2026-02-09 16:44:46)86
- 代码再升级:优化版“获取dump”代码,多机制保障数据读取与保存(字节豆包 | 734点数解答 | 2026-02-10 01:23:31)96
- 代码深度优化:全面检查异常、灵活读取内存,提升可读性与可维护性(字节豆包 | 959点数解答 | 2026-02-10 01:24:14)70
- C语言实现:精准筛选并打印510以内的合数(百度文心 | 540点数解答 | 2024-11-16 16:12:03)87
- C 语言实现:轻松筛选 5 - 10 之间的合数并打印(字节豆包 | 160点数解答 | 2024-11-16 16:17:24)89
- 编程求解:数字币面值累加不同结果及合数数量(字节豆包 | 227点数解答 | 2025-11-22 20:47:55)37
- Python编程:求解数字币面值累加不同结果与合数数量(字节豆包 | 221点数解答 | 2025-11-22 20:48:51)30
- 编程求解:数字币任选累加和的不同结果数与合数个数(字节豆包 | 230点数解答 | 2025-11-30 10:29:20)31