Topcoder SRM 718 Hard

来源:互联网 发布:linux 配置反向dns 编辑:程序博客网 时间:2024/06/07 09:57

链接:https://community.topcoder.com/stat?c=problem_statement&pm=14607&rd=16933

题意:给一个排列p[n],定义f(k)表示它长度为k的所有子序列提取出来,对于每一个按大小顺序标号之后形成的本质不同的排列个数是否为C(n, k),现在你要补全一个排列,使∑f(k)最大,然后字典序最小

题解:考虑f(n - 1) = 1的时候,我们注意到只要相邻两个之差不为1就行了

然后f(n - k) = 1的时候,归纳一下就可以发现只要min(|i - j| + |p[i] - p[j]|) >= k就可以了

证明挺简单的

然后就直接搜就好了

#include <bits/stdc++.h>#define xx first#define yy second#define mp make_pair#define pb push_back#define mset(x, y) memset(x, y, sizeof x)#define mcpy(x, y) memcpy(x, y, sizeof x)using namespace std;typedef long long LL;typedef pair < int, int > pii;class PermutationSubsequence{public:inline bool Dfs(vector < int > &cur, vector < int > &p, int x, int n, int v, int S){if (x == n)return true;if (~p[x]){for (int i = 0; i < x; i ++)if (x - i + abs(p[x] - cur[i]) < v)return false;cur[x] = p[x];if (Dfs(cur, p, x + 1, n, v, S))return true;}for (int i = 0; i < n; i ++)if (S >> i & 1){bool f = 1;for (int j = 0; j < x; j ++)if (x - j + abs(i - cur[j]) < v)f = 0;if (f){cur[x] = i;if (Dfs(cur, p, x + 1, n, v, S ^ 1 << i))return true;}}return false;}vector < int > findBest(vector < int > arr){int n = arr.size(), S = (1 << n) - 1;vector < int > ans(n);for (int i = 0; i < n; i ++)if (~arr[i])S ^= 1 << arr[i];for (int i = n; i; i --)if (Dfs(ans, arr, 0, n, i, S))return ans;}};


原创粉丝点击