问题描述:找出所有形如abcde(三位数乘以两位数)的算式,使得在完成的竖式中,所有数字都属于一个特定的数字集合。输入数字集合(相邻数字之间没有空格),输出所有竖式。每个竖式前应有编号,之后应有一个空行。最后输出解的总数。具体格式见样例输出(为了便于观察,竖式中的空格改用小数点显示,但所写程序中应该输出空格,而非小数点)
思路:这道题因为限定abcde的格式,所以100<=abc<=999,10<=de<=99(不过书上的下限是111和11,也不知为啥,可能我题意理解有些许偏差),只需要遍历所有的可能性就可以了。
关键点一:如何遍历de的个位十位与abc的相乘。
关键点二:如何判断相乘的结果在不在输入的数字集合中。
关键点三:如何输出合适的空格。
由于题目并不复杂,所以使用我并不熟练的C++做。
为了解决关键点二,我将判断这个东西的包装成了一个函数,具体代码如下,思路在注释中(好像又做得很复杂)。
#include<iostream>
#include<string>
#include<sstream>
#include<iomanip>
using namespace std;
int func(int num,string num_char,int flag)
{
char numChar;
int idx;
while (num)//判断abc是不是满足要求
{
numChar = '0' + num % 10;//
idx = num_char.find(numChar);
if (idx == string::npos) {
flag = 0;//如果有一个不在序列之中,就标志其不合法,然后跳出两重循环,执行下一个数
return flag;
}
else
{
num = num / 10;
continue;
}
}
return flag;
}
int main()
{
int num, i,j,flag,number;
string num_char;
string res;
stringstream ss;
while (cin>>num_char)
{
number = 0;
for (i = 111; i <= 999; i++)
{
for (j = 11; j <= 99; j++)
{
flag = 1;
num = i;
flag=func(num, num_char, flag);//判断abc是否合法
num = j;
flag = func(num, num_char, flag);//判断de是否合法
num = i * (j%10);
flag = func(num, num_char, flag);
num = i * (j/10);
flag = func(num, num_char, flag);
num = i*j;
flag = func(num, num_char, flag);//判断i*j是否合法
if (flag)
{
cout << '<' << ++number << '>' << endl;
cout <<" "<<i<< endl;
cout <<"X "<<j<< endl;
cout <<"-----"<< endl;
cout <<setw(5)<< i * (j % 10) << endl;
cout << setw(4) << i * (j / 10) << endl;
cout << "-----" << endl;
cout << i*j<< endl;
}
}
}
cout <<"The number of solutions="<<number<< endl;
}
}
对比一下标准答案的代码,体会标准答案的高明之处:
#include<stdio.h>
#include<string.h>
int main()
{
int count = 0;
char s[20], buf[99];
scanf("%s", s);
for (int abc = 111; abc <= 999; abc++)
{
for (int de = 11; de <= 99;de++)
{
int x = abc * (de % 10), y = abc * (de / 10), z = abc * de;
sprintf(buf, "%d%d%d%d%d", abc, de, x, y, z);
int ok = 1;
for (int i=0; i < strlen(buf); i++)
{
if (strchr(s, buf[i]) == NULL) ok = 0;
}
if(ok)
{
printf("<%d>\n", ++count);
printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n", abc, de, x, y, z);
}
}
}
printf("The number of solutions=%d\n", count);
}
不同之处:
1.标准答案使用了sprintf,可以将所有的数字都作为一个字符串打印到数组中,极大简便了判断,使代码更加简洁。而且执行效率更高,受其启发,修改了代码
#include<iostream>
#include<string>
#include<sstream>
#include<iomanip>
using namespace std;
int func(string num_char,string res,int flag)
{
int idx;
for (int i = 0; i < res.length(); i++)
{
idx = num_char.find(res[i]);
if (idx == string::npos) {
flag = 0;//如果有一个不在序列之中,就标志其不合法,然后跳出两重循环,执行下一个数
return flag;
}
else continue;
}
return flag;
}
int main()
{
int i,j,flag,number;
string num_char;
string res;
stringstream ss;
while (cin>>num_char)
{
number = 0;
for (i = 111; i <= 999; i++)
{
for (j = 11; j <= 99; j++)
{
flag = 1;
ss << i<<j<< i * (j % 10) << i * (j / 10) << i * j;
ss >> res;
flag = func( num_char,res, flag);//判断i*j是否合法
res.clear();
ss.clear();
if (flag)
{
cout << '<' << ++number << '>' <<endl<< " " << i << endl << "X " << j << endl << "-----" << endl << setw(5) << i * (j % 10) << endl << setw(4) << i * (j / 10) << endl << "-----" << endl << i * j << endl;
}
}
}
cout <<"The number of solutions="<<number<< endl;
}
}
image.png
由于本周时间多投资在了另外一边,刷题时间不是很充裕。闲下来后尽量多补点题。