题解:洛谷 P1303 A B Problem

【题目来源】

洛谷:P1303 A*B Problem - 洛谷(luogu.com.cn)

【题目描述】

给出两个非负整数,求它们的乘积。

【输入】

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

【输出】

输出一个非负整数表示乘积。

【输入样例】

1
2

【输出样例】

2

【核心思想】

  1. 问题分析:计算两个非负大整数的乘积,长度可达 \(10^5\) 位(甚至更大)。需要实现高精度乘法,模拟手算竖式乘法的过程。本质是大整数乘法,通过逐位相乘并累加进位来实现。

  2. 算法选择

    • 竖式模拟:将两个数按字符串读入,逆序存入数组(个位在 [0])。对每一位相乘,将结果累加到对应的位置 [i+j],然后处理进位。最后去除前导零。
    • 时间复杂度\(O(la \times lb)\),其中 \(la, lb\) 是位数。对于长度较大的数(如 \(10^5\)),此方法不可行,需使用 FFT/NTT 等快速算法,但本题数据范围较小(原题未明确,通常适合 \(10^3\) 级别),竖式模拟足够。
  3. 关键步骤(以第二个代码版本为例):

    • 读入与逆序存储:将字符串 ab 逆序存入 AB,个位在索引 0
    • 逐位相乘:双重循环 i0la-1j0lb-1
      • C[i+j] += A[i] * B[j]
      • C[i+j+1] += C[i+j] / 10
      • C[i+j] %= 10
    • 去除前导零:结果数组 C 的长度为 lc = la + lb,从高位向低位找到第一个非零位。
    • 输出:逆序输出 C 的有效位。
  4. 时间/空间复杂度

    • 时间复杂度:\(O(la \times lb)\)
    • 空间复杂度:\(O(la + lb)\)
  5. 高精度乘法模拟

    • 逆序存储:与加法类似,个位在索引 0 便于进位。
    • 进位处理:每次累加后,立即处理进位,确保 C[i] 始终保持为个位数。
    • 前导零:乘积可能为 0,需确保输出至少一个 0
    • 适用场景:高精度乘法是算法竞赛的基础内容,用于处理超大整数运算。

【算法标签】

普及- #高精度

【代码详解】

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

int c[2005] = {0};  // 用于存储乘法结果的每一位数字

// 高精度乘法函数:计算两个大整数的乘积
int amulb(string a, string b)
{
    int j1[2005] = {0}, j2[2005] = {0};  // j1 和 j2 用于存储两个大整数的每一位数字
    int lena = a.length(), lenb = b.length();  // lena 和 lenb 分别表示两个大整数的长度
    int len = lena + lenb;  // len 表示乘法结果的最大可能位数

    // 将字符串 a 和 b 转换为 int 数组并翻转(方便从低位到高位计算)
    for (int i = 0; i < lena; i++) j1[lena - i] = a[i] - '0';  // 将 a 的每一位字符转换为数字并翻转
    for (int i = 0; i < lenb; i++) j2[lenb - i] = b[i] - '0';  // 将 b 的每一位字符转换为数字并翻转

    // 逐位相乘
    for (int i = 1; i <= lena; i++)
	{
        for (int j = 1; j <= lenb; j++)
		{
            c[i + j - 1] += j1[i] * j2[j];  // 当前位的乘积累加到 c[i+j-1]
            c[i + j] += c[i + j - 1] / 10;  // 处理进位
            c[i + j - 1] %= 10;  // 当前位只保留个位数
        }
    }

    // 去除结果前导的 0
    while (c[len] == 0 && len > 1)
        len--;

    return len;  // 返回结果的位数
}

int main() {
    string a, b;  // 用于存储输入的两个大整数
    int n;        // 用于存储乘法结果的位数

    cin >> a >> b;  // 输入两个大整数

    // 调用高精度乘法函数,计算 a * b 的结果
    n = amulb(a, b);

    // 输出结果(从高位到低位)
    for (int i = n; i >= 1; i--)
        cout << c[i];

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

const int N = 100005;  // 数组大小,足够大
int A[N], B[N], C[N];  // 存储大数的数组
int la, lb, lc;         // 数组A、B、C的实际长度
string a, b;           // 输入的大数字符串

// 高精度乘法函数
void mul(int A[], int B[], int C[])
{
    // 双重循环,模拟竖式乘法
    for (int i = 0; i < la; i++)
    {
        for (int j = 0; j < lb; j++)
        {
            C[i + j] += A[i] * B[j];  // 累加乘积
            C[i + j + 1] += C[i + j] / 10;  // 进位
            C[i + j] %= 10;  // 保留个位
        }
    }

    // 处理前导零
    while (lc > 0 && C[lc] == 0)
    {
        lc--;  // 去除最高位的0
    }
}

int main()
{
    // 输入两个大数
    cin >> a >> b;

    // 计算长度
    la = a.size();
    lb = b.size();
    lc = la + lb;  // 乘积的最大可能位数是两数位数之和

    // 将字符串逆序存储到数组中
    // 注意:这里存储方式是个位在A[0](与之前代码不同)
    for (int i = la - 1; i >= 0; i--)
    {
        A[la - 1 - i] = a[i] - '0';  // 个位在A[0]
    }

    for (int i = lb - 1; i >= 0; i--)
    {
        B[lb - 1 - i] = b[i] - '0';  // 个位在B[0]
    }

    // 执行高精度乘法
    mul(A, B, C);

    // 输出结果
    for (int i = lc; i >= 0; i--)
    {
        cout << C[i];
    }

    return 0;
}

【运行结果】

12
4
48
posted @ 2026-08-31 09:24  团爸讲算法  阅读(9)  评论(0)    收藏  举报