【洛谷 P1303】A*B Problem + 详细分析

题目链接https://www.luogu.com.cn/problem/P1303

一、题目简介

题目描述

给定两个非负整数,求两个数的乘积。两个整数的数值范围极大,远超普通整型、长整型的存储范围,是经典的高精度乘法模板题。

输入格式

输入共两行,每行输入一个非负整数。

输出格式

输出两个数相乘后的结果,为一个非负整数。

输入输出样例

输入

复制代码
1
2

输出

复制代码
2

二、解题思路详细分析

1、问题难点

普通的 C++ 整型(int)、长整型(long long)存储空间有限,无法存储题目中极大的大数,直接使用 * 乘法运算符会出现溢出、数据错误。因此必须使用高精度算法,模拟人工竖式乘法完成运算。

2、高精度乘法核心原理(竖式模拟)

我们日常手写乘法竖式,就是高精度乘法的核心逻辑,算法完全模拟人工计算步骤:

  1. 倒序存储数字:将输入的字符串大数反转,让数字低位在前、高位在后,方便从低位开始逐位相乘、处理进位,避免数组下标越界和错位问题。
  2. 逐位相乘累加:双重循环遍历两个大数的每一位,根据竖式乘法规则:a 数组第 i 位 × b 数组第 j 位,结果累加到答案数组第 i+j 位。
  3. 统一处理进位:所有位相乘结束后,遍历答案数组,将每一位的数值对 10 取余保留当前位,除以 10 的结果作为进位传递到高一位。
  4. 去除前导零:运算完成后,答案数组高位可能存在多余的 0,需要清空前导零,特殊处理乘积为 0 的情况。

3、图文逻辑演示

举个例子:计算 12 × 34

  • 原数字:a=12、b=34
  • 倒序存储:a=2,1、b=4,3
  • 逐位相乘规则:
    • i=0(2)、j=0(4) → 结果存入 ans0
    • i=0(2)、j=1(3) → 结果存入 ans1
    • i=1(1)、j=0(4) → 结果存入 ans1
    • i=1(1)、j=1(3) → 结果存入 ans2
  • 累加完成后统一进位,最后倒序输出,得到最终结果 408,完全匹配竖式计算结果。

4、算法复杂度分析

设两个大数长度分别为 n、m,算法时间复杂度为 O(n×m),对于本题的数据范围完全够用,是高精度乘法最基础、最通用的模板写法。

三、AC 代码(超详细注释)

cpp 复制代码
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

// 设定最大数组长度,满足题目大数范围
const int MAXN = 2010;

// 定义数组存储大数,初始值默认为0
int a[MAXN], b[MAXN], ans[MAXN];

int main() {
    // 1. 以字符串形式读取两个大数(解决大数无法用整型存储问题)
    string s1, s2;
    cin >> s1 >> s2;
    
    // 获取两个数字的长度
    int len1 = s1.size();
    int len2 = s2.size();
    
    // 2. 将字符串倒序转换为数字数组(低位在前,方便计算)
    for(int i = 0; i < len1; i++)
        a[i] = s1[len1 - i - 1] - '0'; // 字符转整型
    for(int i = 0; i < len2; i++)
        b[i] = s2[len2 - i - 1] - '0';
    
    // 3. 高精度核心:逐位相乘累加
    // a的第i位 * b的第j位,结果累加到ans[i+j]
    for(int i = 0; i < len1; i++) {
        for(int j = 0; j < len2; j++) {
            ans[i + j] += a[i] * b[j];
        }
    }
    
    // 4. 统一处理每一位的进位
    // 最大乘积长度为 len1+len2,遍历所有位
    for(int i = 0; i < len1 + len2; i++) {
        if(ans[i] >= 10) { // 当前位数值大于等于10,需要进位
            ans[i + 1] += ans[i] / 10; // 高位累加进位值
            ans[i] = ans[i] % 10;      // 当前位保留个位数字
        }
    }
    
    // 5. 去除前导零:找到结果的最高位
    int pos = len1 + len2 - 1;
    // 从最高位向下遍历,跳过前导零,保留有效数字
    while(pos > 0 && ans[pos] == 0)
        pos--;
    
    // 6. 从高位到低位倒序输出结果
    for(int i = pos; i >= 0; i--)
        cout << ans[i];
    
    return 0;
}

四、代码核心细节讲解

1、倒序存储的意义

人工计算从低位开始,倒序存储后数组下标从小到大对应数字从低位到高位,进位只需要向下标 +1 的位置传递,逻辑简单、不易出错。

2、乘积下标规律

这是高精度乘法的核心公式:a[i] × b[j] → ans[i+j],完美对应竖式乘法的错位累加规则,是算法的核心精髓。

3、前导零处理

必须保留 pos > 0 的判断,避免两个数相乘为 0 时,将唯一的 0 也删除,导致无输出的错误。

五、总结

本题是高精度乘法万能模板题,掌握本题代码可以解决所有基础大数乘法问题。核心记住三个关键点:倒序存储、错位累加、统一进位、去除前导零。该模板代码简洁、效率稳定,可直接复用在各类 OI、算法竞赛的大数乘法题型中。

相关推荐
小欣加油1 小时前
leetcode2161 根据给定数字划分数组
数据结构·c++·算法·leetcode·职场和发展
吃着火锅x唱着歌1 小时前
深度探索C++对象模型 学习笔记 第五章 构造、解构、拷贝语意学(2)
c++·笔记·学习
玖釉-2 小时前
Vulkan 离屏渲染详解:从 Framebuffer 到后处理、阴影贴图与 Render Texture
c++·windows·计算机视觉·图形渲染
cpp_25012 小时前
P2947 [USACO09MAR] Look Up S
数据结构·c++·算法·题解·单调栈·洛谷
楼田莉子2 小时前
C++20新特性:协程
开发语言·c++·后端·学习·c++20
炘爚2 小时前
phase1:基础框架——编译 + MySQL + 登录/注册
linux·c++
特种加菲猫2 小时前
C++11核心特性深度解析:从列表初始化到lambda与包装器
开发语言·c++
枕星而眠2 小时前
C++ 面向对象核心机制深度解析:多态性、虚函数、虚继承与 final 类
运维·开发语言·c++·后端
智者知已应修善业3 小时前
【51单片机8个LED,已经使用了D1D2,怎么样在不动D1D2的前提下实现D6~D8的流水灯】2024-1-19
c++·经验分享·笔记·算法·51单片机