原英文版题目PDFhttps://onlinejudge.org/external/7/p725.pdfhttps://onlinejudge.org/external/7/p725.pdf
输入正整数n,从小到大输出所有形如abcde/fghij=n的表达式,其中a-j恰好为数字0-9的一个排列(可以有前导0),2=<n<=79.
输入
61 62 0
输出
There are no solutions for 61. 79546 / 01283 = 62 94736 / 01528 = 62
分析
纯暴力(10个for循环)是肯定不行的,我们可以通过等式建立关系,即进行优化:只枚举fghij,通过abcde = fghij*n来得到,再判断abcde是不是另外5个不同的数字,那么我们只要写5个for循环,把复杂度从10^10降到了10^5以下(当然还有更优化的,我这只是一种中规中矩的方法)
本题解法:
- 用set集合来判断数字是否重复
- 在入set中的时候判断下集合的大小变化,没变的说明有重复(具体判断方法看自己,可以入一次看一次,也可以入完再看)
易错点:
- UVA传统格式问题:读入最后一个0后不要换行!所以把换行放在开始好点(第一个不换行,之后换,具体看代码)
- abcde通过乘法得来后要判断下位数!不能超过99999,不能三位数
AC CODE
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
int cnt = 0;
while (cin >> n && n != 0)
{
if ((cnt++) != 0)
cout << endl;
int num;
set<int> s;
int flag = 0;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
for (int k = 0; k < 10; k++)
{
for (int m = 0; m < 10; m++)
{
for (int q = 0; q < 10; q++)
{
num = i * 10000 + j * 1000 + k * 100 + m * 10 + q;
int con = num;
int siz, ff = 0;
//用set集合来判断num的个数
while (con)
{
siz = s.size();
int tmp = con % 10;
s.insert(tmp);
con /= 10;
//判断num里有没有相等的
if (s.size() == siz)
ff = 1;
}
int div = n * num;
//div分子最大不能有6位
if (div > 99999)
{
s.clear();
continue;
}
//set集合判断分子的个数
con = div;
while (con)
{
siz = s.size();
int tmp = con % 10;
s.insert(tmp);
con /= 10;
if (s.size() == siz)
ff = 1;
}
//如果分子分母中都有重复的先clear再continue
if (ff)
{
s.clear();
continue;
}
//如果set中有0 说明分子分母必须是5位数
if (s.find(0) != s.end())
{
if (s.size() == 10)
{
cout << div << " / " << num << " = " << n << endl;
flag = 1;
}
}
else
{
//判断set集合中是9个,WA的问题所在:一开始想当然认为如果集合里是9个,说明分子分母必然是一个4位一个5位
//忽略了如果分子分母都是5位有1位重复,set的结果也是9,就导致最后分子或分母强行在前面加0,出现6位数的结果
//所以在前面入集合的时候添加了判断条件,如果添加前后,集合个数不变,说明有重复
if (s.size() == 9)
{
if (div / 10000 == 0)
{
cout << 0 << div << " / " << num << " = " << n << endl;
flag = 1;
}
else
{
cout << div << " / " << 0 << num << " = " << n << endl;
flag = 1;
}
}
}
s.clear();
}
}
}
}
}
if (!flag)
cout << "There are no solutions for " << n << "." << endl;
}
return 0;
}