C - 小晴天老师系列——竖式乘法
Problem Description
小晴天是ACdream团队中最牛的老师之一,他最擅长数学运算~这天他翻开一本《AC is not a dream》杂志,发现最后一页有一道很经典的思维题,题目很简单,每个框填写一个数字,构成一个竖式,每个数的最高位不能为0,但是有一些数字被隐藏掉了,然后让你根据没有隐藏的数字填出隐藏的数字。
如下图:
然后小晴天二话不说,三下五除二就写出了答案:
然后小晴天就觉得这样的题目太简单了,于是问你是否有办法来求出一道题目有多少种不同的答案呢?(只要有一个方框有不同的数字即为不同的答案)
Input
多组数据,首先是一个整数t(t<=20),表示数据组数。
对于每组数据,用5行表示一个竖式,每行均为一个字符串,仅含有星号(*)与数字('0'~'9')组成,其中星号表示空白
其中第一行为长度为3的字符串。
第二行为长度为2的字符串。
第三行为长度为4的字符串。
第四行为长度为3的字符串。
第五行为长度为5的字符串。
Output
对于每组数据,输出一个整数x,表示符合乘法竖式法则的填法的种类。
Sample Input
2 *** ** 3384 846 ***** 4** ** 3384 846 *****
Sample Output
2 1
Hint
样例1,除了题目中的那种情况,还有这种
而样例2,因为第一个数的百位被固定为4,故只有一种填法。
题目大意:如图所示的一个乘法计算过程,给定你对应位置的数字,*表示可以填任意值域。问你还有多少个填法能够让等式成立。
题解:弄5个for循环,分别对第一行的数和第二行的数进行枚举,然后再根据这个数计算出第三行和第四第五行的结果,再去判断下,产生的数是否都和给定位置的数一样,一样的话,可以填的方法加1。再加N个减枝,可以使原本的效率200+ms变成了20+ms。。。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 using namespace std; 6 int Jude(int Num,char str[])/*产生的数是否和给定的数一样,一样的话返回1,否则返回0*/ 7 { 8 int sign=0,i; 9 char STR[10086]; 10 sprintf(STR,"%d",Num); /*将Num转化为字符串保持在STR中*/ 11 int Len1=strlen(str); 12 int Len2=strlen(STR); 13 if(Len1==Len2) /*长度不一样的话,则结束结束判断,返回0*/ 14 { 15 for(i=0;i<Len1;i++) /*都完全匹配的话,sign才会等于1*/ 16 { 17 if(str[i]=='*'||(str[i]==STR[i]))sign=1; 18 else {sign=0;return sign;}; 19 } 20 } 21 else sign=0; 22 return sign; 23 } 24 int RetInt(int N,char a) /*把字符转化为数字返回*/ 25 { 26 if(a=='*')return N; 27 else return (a-'0'); 28 } 29 int main() 30 { 31 char a[100],b[100],c[100],d[100],e[100]; 32 int Num1,Num2,Num3,Num4,Num5,T; 33 int i,j,k,l,m,sign; 34 scanf("%d",&T); 35 while(T--) 36 { 37 scanf("%s %s %s %s %s",a,b,c,d,e); 38 sign=0; 39 for(i=1;i<=9;i++) 40 { 41 if(a[0]!='*')i=9;/*若当前的数被指定,设置循环节为1*/ 42 for(j=0;j<=9;j++) 43 { 44 if(a[1]!='*')j=9;/*若当前的数被指定,设置循环节为1*/ 45 for(k=0;k<=9;k++) 46 { 47 if(a[2]!='*')k=9;/*若当前的数被指定,设置循环节为1*/ 48 Num1=RetInt(i,a[0])*100+RetInt(j,a[1])*10+RetInt(k,a[2]);/*第一个数*/ 49 for(l=1;l<=9;l++) 50 { 51 if(b[0]!='*')l=9;/*若当前的数被指定,设置循环节为1*/ 52 for(m=2;m<=9;m++) 53 { 54 if(b[1]!='*')m=9; 55 Num2=RetInt(l,b[0])*10+RetInt(m,b[1]);/*获取第二个数*/ 56 if(Num1*Num2<10000)continue;/*剪枝,Num1*Num2结果需要是5位数*/ 57 Num3=Num1*(Num2%10); 58 if(Num3<1000)continue;/*剪枝,Num3结果需要是4位数*/ 59 Num4=(Num2/10)*Num1; 60 if(Num4>=1000)continue;/*剪枝,Num4结果需要是3位数*/ 61 Num5=Num1*Num2; 62 if(Jude(Num3,c)&&Jude(Num4,d)&&Jude(Num5,e)) 63 {sign++;}/*判断如果产生的数能够和给定的数都匹配,则加1*/ 64 } 65 } 66 } 67 } 68 } 69 printf("%d\n",sign); 70 } 71 return 0; 72 }