这道题其实是蓝桥杯的一道真题,其实这题看似很难解,但是如果稍加点化,其实很简单。
思路:因为我们需要选择1-9的数字来组成可以按照题目要求计算成目标数的形式,而且只有一次选用。那么,我们可以想:既然是这9个数字进行组合排列然后成为三个数,我们是不是可以认为这个是全排列之后再进行限制的问题呢?如果是这样的话,这就简单了,这就是一个暴搜,或者说是全排列问题而已。
全排列,你可以使用STL库中的next_permutation,是全排列的运用函数。
另外一种就是暴搜,其实就是用递归的方法写出来全排列。在作者前面的题解中有一个用递归实现全排列的题目,可以找用那个上面的dfs模板进行改进就行。
另外,在改进中,我们只对于全排列搜索完毕之后进行判断即可。在判断过程中需要用到限制条件,既然需要在数组中组成三个数,我们就需要有一个那么功能进行组成数字,因此定义了一个to_num函数,这个函数的功能就是把你选择的区间中的数字变成一个数字,比如数组中有1 2 3三个数,也就是说从0到2位置组成123这个数。就是这么一个功能。
然后,注意一个小细节,就是尽量不要计算除法,所有的除法其实都可以转换成乘法问题,因此这里的a+b/c=n我改成了:a*c+b=n*c这种形式,这样才不会让程序出现不必要的错误。
那么上代码:
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<map>
#include<limits.h>
#include<set>
#define MAX 100
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
typedef long long LL;
int cnt[MAX];
int n;
int ways[MAX];
int count1 = 0;
int to_num(int a, int b) {int sum = 0;for (int i = a; i <= b; i++) {sum = sum * 10 + ways[i];}return sum;
}
void dfs(int k) {if (k > 9) {for (int i = 1; i <= 7; i++) {int num1 = to_num(1, i);for (int j = i + 1; j <= 8; j++) {int num2 = to_num(i + 1, j);int num3 = to_num(j + 1, 9);if (num1 * num3 + num2 == num3 * n)count1++;}}return;}for (int i = 1; i <= 9; i++) {if (!cnt[i]) {ways[k] = i;cnt[i] = 1;dfs(k + 1);ways[k] = 0;cnt[i] = 0;}}
}
int main() {ios::sync_with_stdio(false);cin.tie(NULL); cout.tie(NULL);cin >> n;dfs(1);cout << count1 << endl;return 0;
}