洛谷[模拟与高精度]-P1009 [NOIP1998 普及组] 阶乘之和

洛谷[模拟与高精度]-P1009 [NOIP1998 普及组] 阶乘之和

题目描述
用高精度计算出 S=1!+2!+3!+⋯+n!
其中“!”表示阶乘,例如:5!=5×4×3×2×1

输入格式
一个正整数 n。

输出格式
一个正整数 S,表示计算结果。

输入输出样例
输入 #1
3

输出 #1
9

说明/提示

【数据范围】

对于 100% 的数据,1≤n≤50。

【其他说明】

注,《深入浅出基础篇》中使用本题作为例题,但是其数据范围只有 n≤20,使用书中的代码无法通过本题。
如果希望通过本题,请继续学习第八章高精度的知识。

思路
这道题就是写两个高精运算:高精乘,高精加。
最关键在这个循环怎么写,我定义了两个数组,a和ans。
a存储每一个阶乘项,依次存储1!, 2!, 3!, 4!, … , n!;
ans存储阶乘之和,依次存储1!,1! + 2!, 1! + 2! + 3!, … , 1! + 2! + 3! + … + n!。
每一次循环中,在“上一个阶乘项”的基础上高精乘一个数字算出本次的阶乘项,然后再用算出的结果高精加“上一个阶乘之和”。循环结束之后,ans数组存储的就是所求答案的倒序。
另外幸运的是,这里的高精乘写起来比较简单,因为其中一个乘数最大只有50,只需将另一个乘数数组存储即可(补充:通过之后的学习我知道了其实这里叫高精乘低精)。

代码

#include<bits/stdc++.h>
using namespace std;

int n;
int a[1005]; //存储各个阶乘项
int ans[1005]; //存储阶乘项之和

void mcl(int i) { //高精乘
    int jw = 0;
    for (int j = 1; j <= 1000; j++) {
        a[j] = a[j] * i + jw;
        jw = a[j] / 10; //进位
        a[j] = a[j] % 10; //本位
    }
}

void add() { //高精加
    int jw = 0;
    for (int j = 1; j <= 1000; j++) {
        ans[j] = ans[j] + a[j] + jw;
        jw = ans[j] / 10; //进位
        ans[j] = ans[j] % 10; //本位
    }
}

int main()
{
    //输入
    cin>>n;
    //高精运算
    a[1] = 1;
    for (int i = 1; i <= n; i++) {
        mcl(i); //高精乘
        add(); //高精加
    }
    //输出
    int flag = 0;
    for (int i = 1000; i >= 1; i--) {
        if (ans[i] != 0) { //找到第一个不为0的最高位
            flag = i;
            break;
        }
    }
    for (int i = flag; i >= 1; i--) {
        cout<<ans[i];
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值