UVa 10106 Product

【题目链接】

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1047

【解题思路】

这题借鉴了高精度加法里面的思想,加法部分详情请见链接

http://blog.csdn.net/jcr624/article/details/38128401

我们在手算乘法时,例如12*34,会先算12*4=48,再算0+48=48,接着算12*3=36,将36左移一位变成360,接着将48+360=408,这样乘法就算完成了。以下的核心代码正是模拟了手算这一部分。

bigNumber y;//保存乘法结果
		for (int i = 0; i < len; i ++)//左乘数遍历整数位
		{
			bigNumber mult;//保存左乘数当前位与右乘数相乘的结果
			int temp;
			for (int j = 0, a = 0; a || j < x.len; j ++)//右乘数遍历整数位
			{
				 int k = i+j;//k为两者相乘的结果应存放的位置,如两个乘数第0位和第0位相乘,结果应该在y的第0位
				 temp = a+num[i]*x.num[j];
				 mult.num[k ++] = temp % 10;
				 a = temp/10;
				 mult.len = k;
			}
			y = y+mult;//模拟手算过程,右乘数遍历结束后执行一次加法,直到左乘数遍历结束
		}
跟高精度加法类似,乘法只是将运算符号由+换成了*,进位原理与加法一致,通过O(n^2)的时间复杂度,遍历左乘数和右乘数数位,乘加交替即可得出答案。但是该题目中,需要注意这样的一种特殊情况:

111111*0

如果仅是按照以上算法,会得到000000这样的错误结果,虽然值大小一样,但是输出对格式也是有要求的,这就需要我们去除前面多余的0。

【代码】

#include	<stdio.h>
#include	<string.h>
#include	<stdlib.h>

int MAX(int a, int b)
{
	return a > b ? a : b;
}


typedef struct bigNumber
{
	int num[800];
	int len;

	bigNumber()
	{
		memset(num, 0, sizeof (num));
		len = 0;
	}

	bigNumber operator= (const bigNumber x)
	{
		len = x.len;
		for (int i = 0; i < len; i ++)
		{
			num[i] = x.num[i];
			len = x.len;
		}
		return *this;
	}
	bigNumber operator+ (const bigNumber x) const
	{
		bigNumber y;
		int max_len = MAX(len, x.len);
		for (int i = 0, a = 0; a || i < max_len; i ++)
		{
			int temp = a;
			if (i < len) temp = temp+num[i];
			if (i < x.len) temp = temp+x.num[i];
			y.num[y.len ++] = temp%10;
			a = temp/10;
		}

		return y;
	}

	bigNumber operator* (const bigNumber x) const
	{
		bigNumber y;//保存乘法结果
		for (int i = 0; i < len; i ++)//左乘数遍历整数位
		{
			bigNumber mult;//保存左乘数当前位与右乘数相乘的结果
			int temp;
			for (int j = 0, a = 0; a || j < x.len; j ++)//右乘数遍历整数位
			{
				 int k = i+j;//k为两者相乘的结果应存放的位置,如两个乘数第0位和第0位相乘,结果应该在y的第0位
				 temp = a+num[i]*x.num[j];
				 mult.num[k ++] = temp % 10;
				 a = temp/10;
				 mult.len = k;
			}
			y = y+mult;//模拟手算过程,右乘数遍历结束后执行一次加法,直到左乘数遍历结束
		}

		int flag = 0;
		for (int i = 0; i < y.len; i ++)
		{
			flag = flag | y.num[i];//整数位当中只有有一位不为0,可断定这个整数肯定不是0
		}
		if (flag == 0)
			y.len = 1;//去除前导0

		return y;
	}

	void input(char *x)//将字符串逆转,保存在整型数组里
	{
		len = strlen(x);
		for (int i = 0; i < len; i ++)
		{
			num[i] = x[len-1-i]-'0';
		}
	}

	void output()//逐位输出结果,注意这里的数组保存是逆序的
	{
		for (int i = len-1; i >= 0; i --)
		{
			printf("%d", num[i]);
		}
	}

}bigNumber;


int main()
{
	char str1[300], str2[300];
	while (~scanf("%s %s", str1, str2))
	{
		bigNumber a, b, c;
		a.input(str1);
		b.input(str2);
		c = a*b;
		c.output();
		printf("\n");
	}
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值