[蓝桥杯][基础练习VIP]阶乘计算

该博客介绍了如何使用高精度计算方法解决阶乘问题。通过数组存储大整数,逐位相乘并处理进位。作者在实现过程中遇到了长度更新的问题,经过多次尝试,最终找到解决方案。代码实现可以正确计算较小数值的阶乘,但在处理较大数值时出错,经他人指导修正了循环终止条件,从而能够正确计算阶乘。


原题链接

问题描述

输入一个正整数n,输出n!的值。

其中n!=123*…*n。

算法描述

n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。

将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。

首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。
输入
输入包含一个正整数n,n< =1000。
输出
输出n!的准确值。
样例输入

10

样例输出

3628800

代码

#include<iostream>
using namespace std;
void multiply(int x[], int t)
{
    for (int i = 0; i < x[4999]; i++)
        x[i] *= t;
    for (int i = 0; i < x[4999]; i++)
    {
        int n = x[4999];
        int s = x[i], k = 1;
        x[i] = s % 10;
        while (s /= 10)
        {
            x[i + k++] += s % 10;
            if (i == n - 1) x[4999]++;
        }
    }
}
int main()
{
    int x[10005] = { 1,0 };
    x[4999] = 1;   //存放数字长度
    int num, i = 2, n = 0;
    cin >> num;
    while (i <= num) multiply(x, i++);
    for (int k = x[4999] - 1; k >= 0; k--) cout << x[k];
    return 0;
}

思路

multiply函数:让一个整数按位数保存在一维数组中,让一个数组中每一位与一个数相乘,数组中每个位置存放每一位相乘后的结果

然后再对每个位置依次进位,相当于手写的乘法(每一位与被乘数相乘,再相差一位叠放累加)。

中间出现了一个小问题困惑了我很久,就是那个长度问题,怎么保存并实时更新长度?

一开始想的比较简单,觉得这根本不是问题,直接遍历while(x[i]) n++,这样就有了。后来发现这想法好愚蠢,因为相乘个位数有可能是0,(比较大的阶乘可能连着几十位都是0)所以直接PASS;

后来想着麻烦点但是比较容易实现,就是多加一个参数,每次更新之后再传回实参值,然而就是这个知识点我给忘了,上网搜了也没弄好,在函数里改变形参的值之后,始终没办法传回实参(可能是太着急了),所以又放弃了;

后来想到了一个办法,我只设了一个数组,那就好办,x[0]记录长度不就好了?(受KMP算法的影响),但是要改x[0]很麻烦,所以我直接设数组最后一位x[4999]记录长度。

写到最后觉得已经实现了,验证了一下确实对,但是只能到77,这之后的阶乘算的是错的,之前的阶乘算的是对的,我就以为我的算法没问题,可能是数组在计算较大的值会有错误…

然后给大佬看了下,大佬给我改了循环终止条件,我的循环终止在数字长度的地方,但是数字长度是实时更新的,我之前以为这样会使最后一位更新进位之后让新进的位值再乘一次(这里是想串了,这是和最开始的思路弄混了),其实有判断条件在那里,不会出错的,

所以只要让循环终止条件是数字长度,再实时更新数字长度就行了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值