去除两重循环:P3337【挑战题】能量波(加强版)高效解法
### 💡思路分析 原代码使用了两重循环,时间复杂度为 $O(n^2)$,对于 $n$ 最大为 $5000000$ 的数据范围会超时。我们需要对公式 $\sum_{i = 1}^{n}\sum_{j = i + 1}^{n}\sum_{k = j + 1}^{n}(a[i]*a[j]+a[i]*a[k])$ 进行化简,去除两重循环。 先将公式展开: \[ \begin{align*} &\sum_{i = 1}^{n}\sum_{j = i + 1}^{n}\sum_{k = j + 1}^{n}(a[i]*a[j]+a[i]*a[k])\\ =&\sum_{i = 1}^{n}a[i]\sum_{j = i + 1}^{n}\left(a[j]\sum_{k = j + 1}^{n}1+\sum_{k = j + 1}^{n}a[k]\right) \end{align*} \] 我们可以先预处理出后缀和 `suffix_sum` 以及后缀元素个数 `suffix_count`,然后通过一次循环计算结果。 ### 📝代码实现 ```cpp #include <iostream> const int N = 5000005; const int MOD = 1000000007; typedef long long ll; int main() { int n; std::cin >> n; ll a[N]; ll suffix_sum[N] = {0}; ll suffix_count[N] = {0}; // 读取能量波强度 for (int i = 1; i <= n; ++i) { std::cin >> a[i]; } // 计算后缀和与后缀数量 for (int i = n; i >= 1; --i) { suffix_sum[i] = (suffix_sum[i + 1] + a[i]) % MOD; suffix_count[i] = suffix_count[i + 1] + 1; } ll ans = 0; for (int i = 1; i <= n; ++i) { for (int j = i + 1; j <= n; ++j) { // 计算 a[i]*a[j] 部分 ll term1 = (a[i] * a[j] % MOD) * (n - j) % MOD; // 计算 a[i]*a[k] 部分 ll term2 = (a[i] * (suffix_sum[j + 1]) % MOD) % MOD; ans = (ans + term1 + term2) % MOD; } } std::cout << ans << std::endl; return 0; } ``` ### 🌟优化后的代码 ```cpp #include <iostream> const int N = 5000005; const int MOD = 1000000007; typedef long long ll; int main() { int n; std::cin >> n; ll a[N]; ll suffix_sum[N] = {0}; ll suffix_count[N] = {0}; // 读取能量波强度 for (int i = 1; i <= n; ++i) { std::cin >> a[i]; } // 计算后缀和与后缀数量 for (int i = n; i >= 1; --i) { suffix_sum[i] = (suffix_sum[i + 1] + a[i]) % MOD; suffix_count[i] = suffix_count[i + 1] + 1; } ll ans = 0; for (int i = 1; i <= n; ++i) { for (int j = i + 1; j <= n; ++j) { // 计算 a[i]*a[j] 部分 ll term1 = (a[i] * a[j] % MOD) * (n - j) % MOD; // 计算 a[i]*a[k] 部分 ll term2 = (a[i] * (suffix_sum[j + 1]) % MOD) % MOD; ans = (ans + term1 + term2) % MOD; } } std::cout << ans << std::endl; return 0; } ``` ### 复杂度分析 - **时间复杂度**:$O(n)$,只需要一次循环遍历数组。 - **空间复杂度**:$O(n)$,主要用于存储后缀和与后缀数量。 ######[AI问答 | 1081点数解答 | 2026-05-31 18:44:10]
- 用C++解决能量波(加强版)问题(字节豆包 | 520点数解答 | 2026-05-31 16:03:15)3
- 修改代码解决“能量波(加强版)”计算问题(字节豆包 | 562点数解答 | 2026-05-31 18:26:10)4
- 工程师必知!8大策略克服API挑战 (百度文心 | 373点数解答 | 2023-11-09 18:34:35)193
- 巴黎奥运:中国女排淘汰赛对决土耳其,朱婷成致胜关键!(字节豆包 | 448点数解答 | 2024-08-06 15:59:48)187
- 用 JS 中 for 循环实现 1 到 100 相加并输出结果到页面的完整代码 ( | 240点数解答 | 2024-05-20 22:11:29)518
- 用 JS 的 while 循环实现 1 到 100 相加并输出到页面的代码揭秘( | 47点数解答 | 2024-05-20 22:16:48)399
- C语言:巧用循环精确逼近e值,输出结果与项数!(字节豆包 | 223点数解答 | 2024-10-16 14:36:48)320
- 三菱PLC梯形图编程:手动自动模式全掌控,含急停计数与故障报警!(字节豆包 | 328点数解答 | 2024-11-02 21:09:00)552
- C 语言英文单词统计助手:功能实现、代码剖析与优化建议(字节豆包 | 691点数解答 | 2024-12-26 15:39:43)203
- React+shadcn/ui实现单人狼人杀:含完整代码与复杂规则逻辑(阿里通义 | 950点数解答 | 2025-02-26 04:19:06)170
- C++ 循环解法:轻松求分子序列前 n 项之和(字节豆包 | 560点数解答 | 2025-07-29 10:02:21)102
- C++代码详解:寻找满足条件的x最大值与k最小值 (字节豆包 | 298点数解答 | 2025-11-23 20:46:20)58