问题描述
192这个数很厉害,用它分别乘以1、2、3,会得到:
192 x 1 = 192
192 x 2 = 384
192 x 3 = 576
把这三个乘积连起来,得到192384576,正好是一个1~9的全排列
我们把上面的运算定义为连接乘积:
m x (1 ... n) = k(其中m > 0 且 n > 1,对于上例,m = 192、n = 3、k = 192384576)
即k是把m分别乘以1到n的乘积连接起来得到的,则称k为m和n的连接乘积。
按字典序输出所有不同的连接乘积k,满足k是1~9的全排列
192 x 1 = 192
192 x 2 = 384
192 x 3 = 576
把这三个乘积连起来,得到192384576,正好是一个1~9的全排列
我们把上面的运算定义为连接乘积:
m x (1 ... n) = k(其中m > 0 且 n > 1,对于上例,m = 192、n = 3、k = 192384576)
即k是把m分别乘以1到n的乘积连接起来得到的,则称k为m和n的连接乘积。
按字典序输出所有不同的连接乘积k,满足k是1~9的全排列
输出格式
每个k占一行
样例输出
显然,结果中应包含一行:
192384576
192384576
暴力枚举所有情况。
关键是暴力枚举的范围怎样确定,for循环里从几到几。
可以从最终答案来考虑。
要求最终的是1~9的全排列,所以一定是9位。
读题意,m至少是1。
m为1的时候,n为9才满足9位。
就是1*1,1*2,... ,1*9。然后拼接起来就是123456789满足九位。
n的范围是1~9已经确定了,然后确定m最大为多少。
这个最大值不需要是准确值,只需要包含所有的情况即可。
当m=10000时,m*1 = 10000,m*2 = 20000。拼接起来是10位,已经超过9位了。
暴力枚举的范围确定了,然后就很容易实现了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 vector<string> ans; //存储答案 4 string tostring(int n) { //把数字n转换为字符串 5 string s = ""; 6 while (n > 0) { 7 s.push_back(n % 10 + '0'); 8 n /= 10; 9 } 10 reverse(s.begin(), s.end()); //反转一下 11 return s; 12 } 13 bool check(string s) { //判断s是否是1~9的全排列数 14 if (s.length() != 9) { //如果位数不是9,不是全排列 15 return false; 16 } 17 bool vis[10]; 18 memset(vis, false, sizeof vis); //首先1~9全没出现过,全为false 19 for (int i = 0; i < s.length(); i++) { 20 if (vis[s[i] - '0'] || s[i] == '0') { //如果有重复或有零,不是全排列 21 return false; 22 } 23 vis[s[i] - '0'] = true; //s[i]出现了,标记一下 24 } 25 return true; 26 } 27 int main() { 28 for (int i = 1; i <= 10000; i++) { //暴力 29 string s = ""; 30 for (int j = 1; j <= 9; j++) { 31 s += tostring(i * j); //string的连接 32 if (s.length() > 9) { //如果位数已经超过9,直接跳过 33 continue; 34 } 35 if (check(s)) { 36 ans.push_back(s); 37 } 38 } 39 } 40 sort(ans.begin(), ans.end()); //注意要排序 41 for (int i = 0; i < ans.size(); i++) { 42 cout << ans[i] << endl; 43 } 44 return 0; 45 }