蓝桥杯 算法提高 P1001

问题描述
当两个比较大的整数相乘时,可能会出现数据溢出的情形。为避免溢出,可以采用字符串的方法来实现两个大数之间的乘法。具体来说,首先以字符串的形式输入两个整数,每个整数的长度不会超过8位,然后把它们相乘的结果存储在另一个字符串当中(长度不会超过16位),最后把这个字符串打印出来。例如,假设用户输入为:62773417和12345678,则输出结果为:774980393241726.

输入格式
62773417 12345678

输出格式
774980393241726

解题思路
1.数据接收:先用字符数组接收所给数据,通过空格将两个字符串保存到两个字符数组,再将字符数组转化为int数组;
2.将每一位乘数乘以被乘数所得的结果保存在data结构体中;
3.以结构体最后一个数据为保存最后结果的位置,分别与其他数据相加,注意每靠前一位,就需要多进一位;
4.最后将计算结果进行进位处理。

代码如下:

#include<stdio.h>
#include<string.h>
typedef struct {
	int num[20];
	int len;
}data;
int carry(int *num) {
	int temp;
	temp = *num / 10;
	*num %= 10;
	return temp;
}
void trantion(char a[], int *num, int len) {
	int i;
	for (i = 0; i < len; i++) {
		num[i] = a[i] - 48;
	}
}
int calculate(int *tum, int num[], int temp, int len) {
	int a;
	for (int i = len - 1; i >= 0; i--) {
		if(i==len-1)
			tum[i] = num[i] * temp;
		else
			tum[i] = num[i] * temp + tum[i];
		if (tum[i] > 9 && i != 0)
			tum[i - 1] += carry(&tum[i]);
	}
	if (tum[0] > 9) {
		a = carry(&tum[0]);
		for (int i = len; i > 0; i--)
			tum[i] = tum[i - 1];
		tum[0] = a;
		return len + 1;
	}
	else
		return len;
}
void summation(data *a, data *b, int len, int th) {
	int i;
	for (int j = 0; j < len; j++) {
		b->num[b->len+j] = a->num[a->len - len+j];
	}	
	for (i = 1; i <= b->len; i++) {
		if (th - i - len >= 0) {
			b->num[b->len - i] += a->num[th - i - len];
		}
		else
			break;
	}
	b->len+=len;
	for (i = 0; i < b->len; i++)
		a->num[i] = b->num[i];
	a->len=b->len;
}
int main() {
	char A[8], B[8], C[20];
	data sum[8];
	int num1[8], num2[8];
	for (int i = 0; i < 8; i++)
		for (int j = 0; j < 20; j++)
			sum[i].num[j] = 0;
	gets(C);
	int t;
	for (t = 0; t < strlen(C); t++)//将C字符串分别赋值给A,B字符串
	{
		if (C[t] == ' ') {
			A[t] = '\0';
			break;
		}			
		A[t] = C[t];
	}
	for (int i = 0; i < strlen(C) - t - 1; i++) {
		B[i] = C[i + t + 1];
	}
	B[strlen(C) - t - 1] = '\0';
	int len1 = strlen(A), len2 = strlen(B);
	trantion(A, num1, len1);//字符数组转化为int数组
	trantion(B, num2, len2);
	if(B[0]=='0'||A[0]=='0')
		printf("0");
	else{
		for (int i = 0; i < len2; i++)
			sum[i].len = calculate(sum[i].num, num1, num2[i], len1);//乘数的每一位乘以被乘数,并记录长度
		for (int i = len2 - 2; i >= 0; i--) {
			summation(&sum[len2 - 1], &sum[i], len2 - i - 1, sum[len2 - 1].len);//将data结构体中的数据对应相加
		}
		for(int i=sum[len2 - 1].len-1;i>0;i--){//数据的进位处理
			sum[len2 - 1].num[i-1]+=sum[len2 - 1].num[i]/10;
			sum[len2 - 1].num[i]%=10;
		} 
		if(sum[len2 - 1].num[0]>9){
			int x=sum[len2 - 1].num[0]/10;
			sum[len2 - 1].num[0]%=10;
			for(int j=sum[len2 - 1].len;j>0;j--){
				sum[len2 - 1].num[j]=sum[len2 - 1].num[j-1];
			}
			sum[len2 - 1].num[0]=x;
			sum[len2 - 1].len++;
		}
		for (int i = 0; i < sum[len2 - 1].len; i++)
			printf("%d", sum[len2 - 1].num[i]);
		}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CSDN_SmallAnnum

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值