ACM-大整数乘法

问题描述

求两个不超过 200 位的非负整数的积。

输入数据

有两行,每行是一个不超过200位的非负整数,没有多余的前导 0

输出要求

一行,即相乘后的结果。结果里不能有多余的前导 0,即如果结果是 342,那么就不能输出为 0342。

输入样例

12345678900
98765432100

输出样例

1219326311126352690000

解题思路

        在下面的例子程序中,用 unsigned an1[200]和 unsigned an2[200]分别存放两个乘数,用aResult[400]来存放积。计算的中间结果也都存在 aResult 中。 aResult 长度取 400 是因为两个200 位的数相乘,积最多会有 400 位。 an1[0], an2[0], aResult[0]都表示个位。计算的过程基本上和小学生列竖式做乘法相同。为编程方便,并不急于处理进位,而将进位问题留待最后统一处理。现以 835×49 为例来说明程序的计算过程。

        先算 835×9。 5×9 得到 45 个 1, 3×9 得到 27 个 10, 8×9 得到 72 个 100。由于不急于处理进位,所以 835×9 算完后, aResult 如下:


        接下来算 4×5。此处 4×5 的结果代表 20 个 10,因此要 aResult[1]+=20,变为:


        再下来算 4×3。此处 4×3 的结果代表 12 个 100,因此要 aResult[2]+= 12,变为:


        最后算 4×8。此处 4×8 的结果代表 32 个 1000,因此要 aResult[3]+= 32,变为:


        乘法过程完毕。接下来从 aResult[0]开始向高位逐位处理进位问题。 aResult[0]留下 5,把 4 加到 aResult[1]上, aResult[1]变为 51 后,应留下 1,把 5 加到 aResult[2]上……最终使得 aResult 里的每个元素都是 1 位数,结果就算出来了:


       总结一个规律,即一个数的第 i 位和另一个数的第 j 位相乘所得的数,一定是要累加到结果的第 i+j 位上。这里 i, j 都是从右往左,从 0 开始数。

参考程序

#include <iostream>
#include <cstring>
#define MAX_LEN 200
using namespace std;
unsigned an1[MAX_LEN + 10];
unsigned an2[MAX_LEN + 10];
unsigned aResult[MAX_LEN*2 + 10];
char szLine1[MAX_LEN+10];
char szLine2[MAX_LEN+10];
int main()
{
	gets(szLine1);
	gets(szLine2);
	int i,j;
	int nLen1 = strlen(szLine1);
	int nLen2 = strlen(szLine2);
	//初始化 
	memset(an1,0,sizeof(an1));
	memset(an2,0,sizeof(an2));
	memset(aResult,0,sizeof(aResult));
	j=0;
 	for(i=nLen1-1;i>=0;i--){
	 	an1[j++]=szLine1[i]-'0';
	}
	j=0;
	for(i=nLen2-1;i>=0;i--){
	 	an2[j++]=szLine2[i]-'0';
	}
	for(i=0;i<nLen1;i++){ //每一轮都用 an1 的一位,去和 an2 各位相乘,从 an1 的个位开始
		for(j=0;j<nLen2;j++){
			aResult[i+j] += (an1[i] * an2[j]); //两数第 i, j 位相乘,累加到结果的第 i+j 位
		}
	}
	//下面的循环统一处理进位问题
	for(i=0;i<MAX_LEN*2;i++){
		if(aResult[i] >= 10){
			aResult[i+1] += aResult[i] / 10;
			aResult[i] %= 10;
		}
	}
	//下面输出结果
	bool bStartOutput = false;
	for(i = MAX_LEN * 2;i>=0;i--){
		if(bStartOutput){
			cout<<aResult[i];
		}else if(aResult[i]){
			cout<<aResult[i];
			bStartOutput = true;
		}
	}
	if(!bStartOutput){
		cout<<"0"<<endl;
	}
	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值