题解
阶乘表达式
1 条题解
-
0
解题思路
题目给的表达式是 1!+2!+3!+...+n!,n 最大是 500。500! 有 1135 位,远远超过 long long 能装下的范围,必须用高精度。
分两步思考:
第一步:怎么把表达式里的数字取出来?
表达式中间没有空格,比如 "1!+2!+3!+4!+5!"。我们用循环扫一遍字符串,遇到数字就连续读,拼出一个完整的数 k(可能是一位、两位或三位)。读出来的 k 就是要算阶乘的那个数。
第二步:怎么算阶乘并累加?
- 算 k!:先用数组 tmp 存数字 1(表示 1!),然后依次乘 2、3、...、k。每乘一次,把每一位都乘上这个数,再处理进位。这个过程就是"高精度乘低精度"。
- 累加:算好 k! 之后,把它加到总和数组 ans 里,从个位开始逐位相加,同样要处理进位。
最后从高位到低位把 ans 输出即可。
注意:因为 n 最大 500,表达式很长(n=500 时超过 2000 个字符),存表达式的数组要开大一点。
参考代码
// 用途:计算阶乘表达式 1!+2!+...+n! 的值(高精度加法与乘法) #include <iostream> using namespace std; char expr[5005]; int ans[2005]; // 累加总和,个位放最前面 int tmp[2005]; // 当前某个数的阶乘 int main() { cin >> expr; int len = 0; while (expr[len]) len++; for (int i = 0; i < len; i++) { if (expr[i] >= '0' && expr[i] <= '9') { // 读出一个数 k(1~500,最多 3 位) int k = 0; while (expr[i] >= '0' && expr[i] <= '9') { k = k * 10 + (expr[i] - '0'); i++; } // 计算 k!:先令 tmp = 1,再依次乘 2、3、...、k for (int q = 0; q < 2005; q++) tmp[q] = 0; // 清空,避免残留旧值 tmp[0] = 1; int t = 1; // tmp 的位数 for (int j = 2; j <= k; j++) { int up = 0; for (int p = 0; p < t; p++) { int v = tmp[p] * j + up; tmp[p] = v % 10; up = v / 10; } while (up) { // 新产生的更高位 tmp[t++] = up % 10; up /= 10; } } // 把 k! 加到总和 ans 里 int up = 0, p = 0; while (p < t || up > 0) { int v = (p < t ? tmp[p] : 0) + ans[p] + up; ans[p] = v % 10; up = v / 10; p++; } } // 遇到 '!' 或 '+' 直接跳过 } // 从高位到低位输出 ans int hi = 2000; while (hi > 0 && ans[hi] == 0) hi--; for (int i = hi; i >= 0; i--) cout << ans[i]; cout << endl; return 0; }复杂度分析
设 n 最大 500。算 k! 需要乘 k 次,每次处理 k! 的每一位。k! 大约有 O(k log k) 位,所以算一个阶乘是 O(k² log k)。把所有阶乘加起来,总时间复杂度约为 O(n³ log n)。n=500 时完全可以在时限内跑完。
- 1