题解:

题目难度:中等难度

难点:

1.由于数据太大无法通过整数类型表示,因此用字符串存储结果
2.对于每个字符串从尾部开始进行简单的乘法,在其中考虑进位

知识点:大数相乘

思路:

1.构造multiply(int x, int res[], int res_size)函数,数组res存储被乘数,res_size为被乘数的位数,x为乘数,该函数将两者乘积结果放入数组res(res重新赋值为两者的乘积),该函数返回数组乘积结果的长度。比如10!=3628800已经存储到数组res中,此时res_size=7,计算11!=10! * 11过程如下:

步骤一:

从数组res下标0处开始,依次乘上11,如res[i]11,因为十进制数,考虑向前进位,所以此时res[i]=(res[i]11)%10,向前进位carry = (res[i]*11)/10。按这种方式从下标0计算到下标res_size-1。

步骤二:

需要计算最高为res[res_size-1]所产生的进位。此时产生的进位carry=(res[res_size-1]*11)/10。此时使用while循环判断carry时几位数,把该数从低位开始依次存入res[res_size++]中。
那么调用multiply( 11, int res[], 7)

图片说明

2.计算n!相当于计算1!2=2!,2!3=3!,3!*4=4!,依次类推下去。因此,利用for循环,i从1到n,在其中依次调用multiply(i, res[], res_size),最终n!的结果保存在数组res中,从高位到低位依次输出即可。

#include <iostream>
using namespace std;
// 数组e799bee5baa6e58685e5aeb931333361326235乘法, res_size: 表示有多少位, 返回结果的位数
int multiply(int x, int res[], int res_size) {
    int carry = 0;  // 进位
    for (int i=0; i<res_size; i++) {
        int prod = res[i] * x + carry;
        res[i] = prod % 10;
        carry  = prod/10;
    }

    while (carry!=0) {
        res[res_size] = carry%10;
        carry = carry/10;
        res_size++;
    }
    return res_size;
}

void factorial(int n) {
    int res[36000]; // 10000! 位数不超过36000

    // 初始化
    res[0] = 1;
    int res_size = 1; // 表示有多少位

    // 计算 n!
    for (int x=2; x<=n; x++) {
        res_size = multiply(x, res, res_size);
    }

    for (int i=res_size-1; i>=0; i--) {
        cout<<res[i];
    }
}
int main() {  
    int n;
    cin>>n;
    factorial(n);
}