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

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

2天前

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普及组阶乘之和题解

原创内容 转载请注明出处

分享给朋友:

相关文章

1998年NOIP普及组三连击问题解析与代码详解(洛谷P1008)

1998年NOIP普及组三连击问题解析与代码详解(洛谷P1008)

一、题目解读1998年NOIP普及组三连击(洛谷P1008)要求寻找三个连续整数a、b、c(其中b=2a,c=3a),且这三个数的各位数字恰好组成1-9的排列(不重复且不包含0)。题目需输出符合条件的...

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

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

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

【1999NOIP普及组】(洛谷P1016)旅行家的预算解题报告(附代码+注释)

【1999NOIP普及组】(洛谷P1016)旅行家的预算解题报告(附代码+注释)

一、题目解读题目要求解决旅行家从起点到终点(D1公里)的预算问题,需在沿途N个加油站中规划加油策略,使总费用最小化。每个加油站有不同油价和距离,汽车每升油可行驶D2公里,初始油量为C升,终点无加油站。...

洛谷2095题解题报告:贪心+分类计数的优化策略

洛谷2095题解题报告:贪心+分类计数的优化策略

一、题目解读洛谷2095题要求处理一组食品数据,每个食品包含脂肪含量和类别。用户需在满足类别消费限制的前提下,选择脂肪含量最高的食品组合,计算总脂肪值。题目核心在于平衡脂肪优先级与类别数量约束,考验对...

发表评论

访客

看不清,换一张

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