解题思路:
先分析问题,不要盲目暴力。
如果直接搜索,使用先求全排列,然后逐位选取数字,再组合的方法,复杂度在P(9,4)*P(5,2)*3! = 362880 > 3*10^5上下,可能在1s的时间里是无法承受的。
实际上,题目已经给出了暗示,四位数 = 两位数 * 三位数 是一种可行的方案。一共9个数字,如果是 四位数 = 四位数 * 一位数 应当也可能存在解。那么其他情况呢?
五位数 = 两位数 * 两位数——显然不可以,因为即便是最大的两位数99乘以99,积也是四位数。除此之外的一位数 * 三位数等其他方案同样也是显然不行的。
三位数的方案显然是不可以的,因为剩下的6个数字,无论怎么分,位数就大于等于三位,显然都太大了。
往两边的试探性搜索都以失败而告终,专心枚举 四位数 = 两位数 * 三位数 和 四位数 = 四位数 * 一位数 两种方案即可。
注意事项:
1.注意适当地剪枝,将出现重复数字和0的数字,以及乘积位数超过4位的情况及时剔除。
2.不要漏掉 四位数 = 四位数 * 一位数 的方案
3.题目要求按照第一标尺乘积大小,第二标尺较小乘数的大小由小到大输出,自行实现cmp比较函数,调用stl库的sort函数,详见代码
4.耗时在40ms上下
PS:如果超时,可以在本地把答案全部算出来,然后直接输出,附赠直接输出答案的代码:
#include<iostream>
using namespace std;
int main()
{
cout << "4396 = 28 x 157" << endl
<< "5346 = 18 x 297" << endl
<< "5346 = 27 x 198" << endl
<< "5796 = 12 x 483" << endl
<< "5796 = 42 x 138" << endl
<< "6952 = 4 x 1738" << endl
<< "7254 = 39 x 186" << endl
<< "7632 = 48 x 159" << endl
<< "7852 = 4 x 1963" << endl;
return 0;
}
参考代码:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <stdio.h>
using namespace std;
typedef struct Expression {
int c;//乘积
int a;//较小的乘数
int b;//较大的乘数
};
vector<Expression> ans;
bool cmp(Expression a, Expression b)
{
if (a.c < b.c)
return true;
else if (a.c == b.c)
{
if (a.a < b.a)//次级条件
return true;
else
return false;
}
else
return false;
}
bool check(int n)
{
bool ret = true;
bool vis[10] = { false };
while (n)
{
int curNum = n % 10;
if (vis[curNum] || curNum == 0)
{
ret = false;
break;
}
vis[curNum] = true;
n /= 10;
}
return ret;
}
void pushNumToSet(int n, set<int>& s)
{
while (n)
{
int curNum = n % 10;
s.insert(curNum);
n /= 10;
}
}
void solve()
{
//1位乘以4位
for (int a = 1; a <= 9; a++)
{
for (int b = 1000; b <= 9999; b++)
{
if (!check(b))
continue;
int c = a*b;
if (c > 9999)
break;
set<int> numSet;
pushNumToSet(a, numSet);
pushNumToSet(b, numSet);
pushNumToSet(c, numSet);
if (numSet.size() == 9)
{
if (find(numSet.begin(), numSet.end(), 0) == numSet.end())
{
Expression expr;
expr.a = a;
expr.b = b;
expr.c = c;
ans.push_back(expr);
}
}
}
}
//2位乘以3位
for (int a = 10; a <= 99; a++)
{
if (!check(a))
continue;
for (int b = 100; b <= 999; b++)
{
if (!check(b))
continue;
int c = a*b;
if (c > 9999)
break;
set<int> numSet;
pushNumToSet(a, numSet);
pushNumToSet(b, numSet);
pushNumToSet(c, numSet);
if (numSet.size() == 9)
{
if (find(numSet.begin(), numSet.end(), 0) == numSet.end())
{
Expression expr;
expr.a = a;
expr.b = b;
expr.c = c;
ans.push_back(expr);
}
}
}
}
}
int main(int argc, char** argv)
{
solve();
sort(ans.begin(), ans.end(), cmp);
for (vector<Expression>::iterator it = ans.begin(); it < ans.end(); it++)
cout << it->c << " = " << it->a << " x " << it->b << endl;
return 0;
}0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复