UVa : 338 - Long Multiplication
問題概要
http://uva.onlinejudge.org/external/3/338.html
入出力を見ればわかりますが, 掛け算のひっ算の過程を出力せよという問題です.
ひっ算の途中で, 0だけの行が出てくる場合は, 出力に含めないようにします.
0の行を除いた上で, ひっ算の途中計算が, 2行未満になる場合は, 答えだけを出力する必要があります.
例えば,
10
10
--
10
-
- -
100
はダメです.
ひっ算の途中計算は, 1行しかないので, 次のように答えの行だけを出力するようにします.
10
10
--
100
アルゴリズム
問題概要によると, 入力される値は, 最大10ケタあります.
つまり, 最大の掛け算では, 9999999999 * 9999999999 を計算しなければならないことになります.
この計算, 残念ながら, 2^64 に収まりません.
面倒ですが, 文字列で管理しましょう.
プログラム
久々に, C言語で書いてみました.
#include <stdio.h> #include <string.h> //整数 a (文字列管理) * b を行い, s に代入する(文字列) void mult(char *s,char *a,int b){ int i; int len = strlen(a); int cal[100]; for(i=0;i<len;i++){ cal[i] = (a[i] - '0') * b; } //繰り上げ処理 for(i=len-1;i>0;i--){ if(cal[i] >= 10){ cal[i-1] += cal[i] / 10; cal[i] %= 10; } } //aより桁数が増える場合 if(cal[0] >= 10){ s[0] = (cal[0] / 10) + '0'; s[1] = (cal[0] % 10) + '0'; for(i=1;i<len;i++){ s[i+1] = cal[i] + '0'; } s[len+1] = '\0'; } //aと桁数が一緒の場合 else{ for(i=0;i<len;i++){ s[i] = cal[i] + '0'; } s[len] = '\0'; } } int main(void){ int i,j; int alen,blen,len,anslen,max,maxAB; int cal[100]; int cnt; char a[100],b[100]; char s[100][100]; char ans[100]; while(scanf("%s%s",a,b) == 2){ alen = strlen(a); blen = strlen(b); cnt = 0; memset(cal,0,sizeof(cal)); for(i=0;i<blen;i++){ mult(s[i],a,b[blen-i-1]-'0'); if(s[i][0] == '0'){ //0の行はとばす continue; } cnt++; //0でない行をカウント len = strlen(s[i]); for(j=0;j<len;j++){ cal[j+i] += s[i][len-j-1] - '0'; } } //繰り上げ処理 for(i=0;i<30;i++){ if(cal[i] >= 10){ cal[i+1] += cal[i] / 10; cal[i] %= 10; } } while(i > 0 && cal[i] == 0) i--; for(j=0;i>=0;i--,j++){ ans[j] = cal[i] + '0'; } ans[j] = '\0'; anslen = j; maxAB = (alen > blen ? alen : blen); max = (maxAB > anslen ? maxAB : anslen); //ひっ算の途中計算が, 2行以上ある場合は, 過程を出力 if(cnt >= 2){ for(i=0;i<max-alen;i++) putchar(' '); puts(a); for(i=0;i<max-blen;i++) putchar(' '); puts(b); for(i=0;i<max-maxAB;i++) putchar(' '); for(i=0;i<maxAB;i++) putchar('-'); putchar('\n'); for(i=0;i<blen;i++){ if(s[i][0] == '0') continue; len = strlen(s[i]); for(j=0;j<max-len-i;j++) putchar(' '); puts(s[i]); } for(i=0;i<max;i++) putchar('-'); putchar('\n'); puts(ans); } //2行未満の場合, 答えだけを出力 else{ for(i=0;i<max-alen;i++) putchar(' '); puts(a); for(i=0;i<max-blen;i++) putchar(' '); puts(b); for(i=0;i<max-maxAB;i++) putchar(' '); for(i=0;i<maxAB;i++) putchar('-'); putchar('\n'); for(i=0;i<max-anslen;i++) putchar(' '); puts(ans); } putchar('\n'); } return 0; }