NOIP1998P2 阶乘之和 题解

(题目描述略)

本题可以用高精度暴力求解,但代码量过大。我们在这里有一种优化的思路。

由于 n! + (n - 1)! + (n - 2)! + .. + 2! + 1! = (..((((0 + 1) * n + 1) * (n - 1) + 1) * (n - 2) + 1) * .. * 2 + 1) * 1,所以我们可以得出以下算法:

第一步:令 ans := 0,读入 n;
第二步:令 ans := (ans + 1) * n,令 n := n - 1;
第三步:判断是否 n > 0,若是则转第二步,若否则转第四步;
第四步:输出 ans。

将以上算法套入高精度,即为本题的优化算法。

代码如下:

#include"stdio.h"
#include"string.h"
int answer[20];
int main()
{
    int m,n;
    scanf("%d",&n);
    memset(answer,0,sizeof(answer));
    answer[m=0]=n;
    while(--n)
    {
        answer[0]++;
        for(int i=0;i<=m;i++)
            answer[i]*=n;
        for(int i=0;i<=m;i++)
            answer[i+1]+=answer[i]/10000,
            answer[i]%=10000;
        if(answer[m+1]>0)
            m++;
    }
    printf("%d",answer[m--]);
    while(m>=0)
        printf("%04d",answer[m--]);
    return 0;
}

为了方便起见,作者的代码采用了万进制的优化方法。

经过以上优化,我们可以发现,相对于朴素算法而言,我们已经省去了一个高加高的过程,并节省了一个高精度数组。更为重要的是,我们压缩了代码量,使之更易编写和调试。

由于本题数据过弱,所以不需要高精度快速幂 O(logn) 的算法,只需要朴素的 O(n) 的算法便足以通过。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值