当前位置:首页 > 入门组 > 1998年NOIP普及组阶乘之和题解(洛谷P1009) | 高精度算法实现与解题思路分析

1998年NOIP普及组阶乘之和题解(洛谷P1009) | 高精度算法实现与解题思路分析

6个月前 (08-26)

1998年NOIP普及组阶乘之和题解(洛谷P1009) | 高精度算法实现与解题思路分析 NOIP普及组 洛谷 高精度算法 阶乘之和 大数运算 第1张

一、题目解读

1998年NOIP普及组阶乘之和洛谷P1009)要求计算前n个自然数的阶乘之和,即 ∑(i=1 to n) i!。由于阶乘结果随n增长迅速膨胀(例如,n=20时,20!已远超常规整数类型上限),题目核心难点在于如何高精度处理大数相加与乘法运算。传统数据类型无法直接存储计算结果,需设计自定义高精度算法解决。

二、解题思路

用户提供的代码采用高精度分治策略

1. 核心思想:通过动态数组存储大数,逐位模拟乘法和加法过程,解决数值溢出问题。

2. 关键步骤:

    定义高精度乘法函数 multiply(a, b),实现大数a与整数b的乘积(逐位相乘+进位处理)。

    定义高精度加法函数 add(a, b),实现两个大数a与b的逐位相加(考虑位数差异与进位)。

    主循环:从1到n依次计算i的阶乘,并累加至总和。

3. 优化点:逆序输出结果避免字符串反转,提升效率。

三、解题步骤

1. 初始化:

    总和 sum 初始化为向量[0],阶乘 fact 初始化为[1]。

2. 循环计算:

    外层循环i从1到n,逐次处理每个阶乘项。

    内层:

        a. 计算 fact = multiply(fact, i),更新当前阶乘。

        b. 累加 sum = add(sum, fact),将阶乘加入总和。

3. 输出处理:逆序遍历sum向量,输出各位数字(因存储为逆序,直接输出即正确结果)。

四、代码与注释

#include <iostream>
#include <vector>
using namespace std;

// 高精度乘法:大数a乘以整数b
vector<int> multiply(vector<int> a, int b) {
    vector<int> c;
    int carry = 0; // 进位
    for (int i = 0; i < a.size(); i++) {
        int temp = a[i] * b + carry; // 当前位乘积+进位
        c.push_back(temp % 10); // 取个位存入结果
        carry = temp / 10; // 更新进位
    }
    while (carry) { // 处理末尾进位
        c.push_back(carry % 10);
        carry /= 10;
    }
    return c;
}

// 高精度加法:大数a加上大数b
vector<int> add(vector<int> a, vector<int> b) {
    vector<int> c;
    int carry = 0;
    for (int i = 0; i < max(a.size(), b.size()); i++) { // 按较长位数对齐
        int sum = carry; // 初始化本位和
        if (i < a.size()) sum += a[i];
        if (i < b.size()) sum += b[i];
        c.push_back(sum % 10);
        carry = sum / 10;
    }
    if (carry) c.push_back(carry); // 处理最高位进位
    return c;
}

int main() {
    int n;
    cin >> n; // 输入n
    
    vector<int> sum(1, 0); // 总和初始化为[0]
    vector<int> fact(1, 1); // 阶乘初始化为[1]
    
    for (int i = 1; i <= n; i++) {
        fact = multiply(fact, i); // 计算i的阶乘
        sum = add(sum, fact); // 累加至总和
    }
    
    // 逆序输出结果
    for (int i = sum.size() - 1; i >= 0; i--) {
        cout << sum[i];
    }
    cout << endl;
    
    return 0;
}

五、总结

1. 算法价值:高精度算法是解决大数运算的经典范式,适用于竞赛、数学计算等领域。

2. 代码优化方向:可进一步优化乘法复杂度(如Karatsuba算法),或采用位运算加速。

3. 实践意义:通过手写乘加逻辑,深化对数值底层处理的理解,为更复杂算法(如高精度除法)奠定基础。

参考:1998NOIP普及组阶乘之和题解

原创内容 转载请注明出处

分享给朋友:

相关文章

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

题目重解:数字三角形是一个经典的动态规划问题,给定一个由数字组成的三角形结构,从顶部出发,每次可以移动到下方相邻的数字,最终到达底部。我们需要找到一条路径,使得路径上经过的数字总和最大。这个问题可以很...

【洛谷1184题解析】用C++高效解决地点匹配问题(附代码与解题思路)

【洛谷1184题解析】用C++高效解决地点匹配问题(附代码与解题思路)

一、题目解读洛谷1184题要求处理一组地点列表与行程记录,统计其中匹配的天数。题目难点在于高效处理带有空格的字符串输入,以及快速判断每日行程是否在高手可去地点集合中。需要兼顾输入格式解析与算法效率。二...

【CSP-J 2021】分糖果题(洛谷P7909)解题思路与代码解析

【CSP-J 2021】分糖果题(洛谷P7909)解题思路与代码解析

一、题目解读2021年CSP-J分糖果问题(洛谷P7909)要求计算在给定的糖果数量n及区间范围L和R下,糖果分配后剩余糖果数的最大值。核心目标是通过数学逻辑确定R mod n的最大可能余数,需考虑区...

2025年蓝桥杯省赛A组抽奖题(洛谷P12140)解析:代码思路与解题步骤详解

2025年蓝桥杯省赛A组抽奖题(洛谷P12140)解析:代码思路与解题步骤详解

一、题目解读2025年蓝桥杯省赛A组中的“抽奖”题目(对应洛谷P12140)要求处理三个转轮抽奖机制。每个转轮有n个数字,通过m次操作转动转轮,每次根据三个转轮对齐的数字组合计算得分。题目需判断三种奖...

2013年NOIP普及组车站分级题解(洛谷P1983)— 图论与拓扑排序的实战应用

2013年NOIP普及组车站分级题解(洛谷P1983)— 图论与拓扑排序的实战应用

一、题目解读“车站分级”是2013年NOIP普及组的经典题目(洛谷P1983)。题目要求根据车次停靠信息,为每个车站分配级别:若某车站被所有车次停靠,则为最高级;若仅被部分车次停靠,则级别取决于其连接...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。