top1编程
← 返回题目
题解

阶乘表达式

1 条题解

  • 0
    @ 2026-8-4 1:18:03

    解题思路

    题目给的表达式是 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