题目描述
求两数的积。
输入格式
两行,两个整数。
输出格式
一行一个整数表示乘积。
输入
1
2
输出
2
说明/提示
每个数字不超过 10^2000,需用高精。
读入数据
注释中的读入,虽然在自己dev编译系统上编译时不会有任何问题,但是提交是不对的
Linux操作系统中对换行的处理与Windows不一样造成的
(刘汝佳的《算法竞赛入门经典》,电子版93页)
/*
for(int i = 0; ;i++) {
// scanf("%c", &a[i]);
//a[i] = getchar();
if(a[i] == '\n') {
a[i] = '\0';
break;
}
}
for(int i = 0; ;i++) {
scanf("%c", &b[i]);
//b[i] = getchar();
if(b[i] == '\n') {
b[i] = '\0';
break;
}
}
*/
scanf("%s", a);
scanf("%s", b);
逆序存储
模拟乘法运算过程,(当然,按原顺序也是可以的,之后进行运算的时候注意循环从最后一个数开始)
int la = strlen(a), lb = strlen(b);
for(int i = 1; i <= la; i++) {
x[i] = a[la - i] - '0';
//printf("x[%d] = %d\n", i, x[i]);
}
for(int i = 1; i <= lb; i++) {
y[i] = b[lb - i] - '0';
//printf("y[%d] = %d\n", i, y[i]);
}
la 或 lb - i 让下标从最后一个开始,倒叙过来换成具体数据存储。
模拟乘法
x中的数 * y中的数, 所以外层for循环是x的下标,内层是y的下标。
c中的下标,可以发现用i + j - 1即可解决
for(int i = 1; i <= lb; i++) {
for(int j = 1; j <= la; j++) {
c[i + j - 1] += x[j] * y[i];
if(c[i + j - 1] > 9) {
c[i + j] += c[i + j - 1] / 10;
c[i + j - 1] %= 10;
}
}
}
确定长度,删去前导零
比如100 * 100, 他的长度是绝对不可能超过两个数的长度之和,有上面的图片可知,相加的时候,有重叠部分(如序号2处)。
而当两个数中其中一个是0时,其结果也是零,但是长度为1,要输出0,所以长度至少要为1,也就是while 中有 len > 1.
int len = la + lb;
while(!c[len] && len > 1) {
len--;
}
最后逆序输出
注意是i > 0因为之前是从1开始而不是0.
for(int i = len; i > 0; i--) {
printf("%d", c[i]);
}
下面附上全部代码
#include<stdio.h>
#include<string.h>
char a[10000005], b[10000005];
int x[10000005], y[10000005], c[10000005];
int main() {
scanf("%s", a);
scanf("%s", b);
int la = strlen(a), lb = strlen(b);
for(int i = 1; i <= la; i++) {
x[i] = a[la - i] - '0';
}
for(int i = 1; i <= lb; i++) {
y[i] = b[lb - i] - '0';
}
for(int i = 1; i <= lb; i++) {
for(int j = 1; j <= la; j++) {
c[i + j - 1] += x[j] * y[i];
if(c[i + j - 1] > 9) {
c[i + j] += c[i + j - 1] / 10;
c[i + j - 1] %= 10;
}
}
}
int len = la + lb;
while(!c[len] && len > 1) {
len--;
}
for(int i = len; i > 0; i--) {
printf("%d", c[i]);
}
return 0;
}