1 条题解
-
3
题解
思路1
这是最常用的思路,我们观察可以发现这是一个全排列, 就相当于下一个全排列。
我们可以用系统函数
next_permutation
:#include<bits/stdc++.h> using namespace std; int n, m, ord[10005]; int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &ord[i]); for (int i = 1; i <= m; i++) next_permutation(ord + 1, ord + n + 1); // +1 for (int i = 1; i <= n; i++) printf("%d ", ord[i]); printf("\n"); return 0; }
当然你也可以选择手写,用dfs,这里就不出示代码了。
思路2
我们
没事找事拓宽思维,可以把全排列转换为变进制数。对于第 根手指,它有 种选择,根据位值原理,要想让每个数对应一个全排列,就要让这一位数是 进制的。
之后我们把变进制数加上 ,再转换回来,就可以了。
我们来看一个实例: 将 变成变进制数:
- 第 位 有 种选择 的第 种,故变为 (从0开始)
- 第 位 有 种选择 的第 种,故变为
- 第 位 有 种选择 的第 种,故变为
- 第 位 有 种选择 的第 种,故变为
- 第 位 有 种选择 的第 种,故变为
最后,排列 变成了
,根据每一位的进制进位:
- 第 位是 进制的,进 得 。
- 第 位位是 进制的,满 进 得 。
- 第 位是 进制的,满 进 得 。
- 第 位是 进制的,,不进位,得
我们将他变回火星数:
- 第 位 表示这位应选择 的第 种,即
- 第 位 表示这位应选择 的第 种( 被选过了),即
- 第 位 表示这位应选择 的第 种,即
- 第 位 表示这位应选择 的第 种,即
- 第 位 表示这位应选择 的第 种,即
其实这也叫康托展开。
最后写出代码:
#include<bits/stdc++.h> using namespace std; int n, m, a[10005]; bool used[10005] = {0}; int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); int x = a[i]; for (int j = 1; j <= a[i]; j++) x -= used[j]; used[a[i]] = 1; a[i] = x - 1; } a[n] += m; for (int i = n; i >= 1; i--) { a[i - 1] += a[i] / (n - i + 1); a[i] %= n - i + 1; } memset(used, 0, sizeof(used)); for (int i = 1; i <= n; i++) { for (int j = 0;j <= a[i]; j++) if (used[j]) a[i]++; printf("%d ", a[i] + 1); used[a[i]] = 1; } printf("\n"); return 0; }
- 1
信息
- ID
- 1706
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 114
- 已通过
- 71
- 上传者