特殊乘法 - 九度教程第39题
题目
时间限制:1 秒 内存限制:32 兆 特殊判题:否
题目描述:
写个算法,对 2 个小于 10 0000 0000 的输入,求结果。
特殊乘法举例:123 * 45 = 14 +15 +24 +25 +34+35
输入:
两个小于 1000000000 的数
输出: 输入可能有多组数据,对于每一组数据,输出 Input 中的两个数按照题目 要求的方法进行运算后得到的结果。
样例输入:
123 45
样例输出:
54
来源:
2010 年清华大学计算机研究生机试真题
核心任务是将两个整数各个数位上的数字拆开,然后再将这些数字两两相乘后求和得到答案。如样例所示, 将整数 123 拆解成 1、2、3,将整数 45 拆解成 4、5,然后将它们两两相乘后相加就得到了答案54。
%运算符求余数的运算可以应用在数位拆解。数位拆解即把一个给定的数字(如3241)各个数位上的数字拆开,即拆成3、2、4、1。
设一个四位数x,该四位数千位为a,百位为b,十位为c,个位为d。那么x满足方程:
x = a * 1000 + b * 100 + c * 10 + d
//只需确定x被10除的余数就能确定其个位上的数字d
x % 10 = ( a * 1000 + b * 100 + c * 10 + d )% 10
x % 10 = a * 1000 % 10 + b * 100 % 10 + c * 10 % 10 + d % 10
x % 10 = d
只需依次将其他数位上的数字移动到个位,然后重复以上过程就可以获得其他数位上的数字。
x / 10 = ( a * 1000 + b * 100 + c * 10 + d) / 10
x / 10 = a * 1000 / 10 + b * 100 / 10 + c * 10 / 10 + d / 10
x / 10 = a * 100 + b * 10 + c
对x做整除,使x除以整数10,即可将十位上的数字移动到个位上,百位上的数字移动到十位数字,其他位依次类推。
#include <stdio.h>
int main()
{
int a,b;
while(scanf("%d%d",&a,&b)!=EOF){
int buf1[11],buf2[11],size1=0,size2=0;
//用buf1,buf2分别保存从两个整数中拆解出来的数位数字
//其数量由size1,size2表示
while(a!=0){//数位拆解,只要当a大于0就不断重复拆解过程
buf1[size1++]=a%10;//取当前个位上的数字并保存
a/=10;
}
while(b!=0){
buf2[size2++]=b%10;
b/=10;
}
int ans=0;
for(int i=0;i<size1;i++){
for(int j=0;j<size2;j++){
ans+=buf1[i]*buf2[j];
}
}
printf("%d\n",ans);
}
return 0;
}
假设输入数据为 0,那么当程序运行到 while循环时,由于被分解整数已经为 0,程序将直接跳过循环,而使数位分解失败。可以在对整数做数位分解之前,对该整数是否为 0 进行特判,若其为 0,则分解结果仅为一个数字 0。
也可以采用将输入数据当做字符串的技巧,直接将两个数字以字符串的形式保存起来,再依次遍历这个字符串,通过字符与字符 '0’的 ASCII 值的差,计算字符所表示的数字值,从而完成数字的拆解。这种方法, 虽然没有使用任何的数学技巧,但它思路简洁、写法清晰。代码如下:
#include <stdio.h>
int main()
{
char a[11],b[11];
while(scanf("%s%s",a,b)!=EOF){
int ans=0;
for(int i=0;a[i]!=0;i++){
for(int j=0;b[j]!=0;j++){
ans+=(a[i]-'0')*(b[j]-'0');
}
}
printf("%d",ans);
}
return 0;
}