题目链接:https://codeforces.com/gym/102012/problem/I
题意:问有多少个 1 到 n 的排列,使得用给定的 k 个比较器(使 au 和 av 有序)排序后,整个序列的最长上升子序列为 n - 1。
题解:先处理出全部最长上升子序列为 n - 1 的排列,然后枚举每个比较器使用与否,计数即可。(题目卡常,dfs要加引用...)
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define mst(a,b) memset((a),(b),sizeof(a)) 6 #define mp(a,b) make_pair(a,b) 7 #define pi acos(-1) 8 #define pii pair<int,int> 9 #define pb push_back 10 const int INF = 0x3f3f3f3f; 11 const double eps = 1e-6; 12 const int maxn = 1e6 + 10; 13 const int maxm = 1e5 + 10; 14 //const ll mod = 998244353; 15 16 set<vector<int>>se; 17 int a[55],u[15],v[15]; 18 19 int dfs(vector<int>&vec,int now) { 20 if(now < 0) return 1; 21 int l = u[now], r = v[now], ans = 0; 22 if(vec[l] < vec[r]) { 23 ans += dfs(vec,now - 1); 24 swap(vec[l],vec[r]); 25 ans += dfs(vec,now - 1); 26 swap(vec[l],vec[r]); 27 } 28 return ans; 29 } 30 31 int main() { 32 #ifdef local 33 freopen("data.txt", "r", stdin); 34 // freopen("data.txt", "w", stdout); 35 #endif 36 for(int i = 0; i < 55; i++) a[i] = i; 37 int t; 38 scanf("%d",&t); 39 while(t--) { 40 se.clear(); 41 int n,k,mod; 42 scanf("%d%d%d",&n,&k,&mod); 43 for(int i = 0; i < k; i++) { 44 scanf("%d%d",&u[i],&v[i]); 45 u[i]--, v[i]--; 46 } 47 int ans = 0; 48 for(int i = 0; i < n; i++) { 49 vector<int>vec; 50 for(int j = 0; j < i; j++) vec.push_back(j); 51 for(int j = i + 1; j < n; j++) vec.push_back(j); 52 for(int j = 0; j < n; j++) { 53 vector<int>v; 54 for(int k = 0; k < j; k++) v.push_back(vec[k]); 55 v.push_back(i); 56 for(int k = j; k < vec.size(); k++) v.push_back(vec[k]); 57 if(se.find(v) == se.end()) ans += dfs(v,k - 1); 58 se.insert(v); 59 } 60 } 61 printf("%d ",ans % mod); 62 } 63 return 0; 64 }