比赛 |
round 2『计协冻梨桐难霍』 |
评测结果 |
AAAAAAAAAAAAAAAAAA |
题目名称 |
交换礼物 |
最终得分 |
100 |
用户昵称 |
darkMoon |
运行时间 |
3.748 s |
代码语言 |
C++ |
内存使用 |
36.86 MiB |
提交时间 |
2024-11-22 08:17:21 |
显示代码纯文本
- #include<bits/stdc++.h>
- #define int long long
- using namespace std;
- auto mread = [](){int x;scanf("%lld", &x);return x;};
- const int N = 25, M = 270005;
- int n = mread(), a[N][N], belong[N][N], f[M][N][2];
- // f_now_i 表示 now 状态里面的礼物可以重新分配,可分配的奶牛中最靠右的奶牛分到的礼物是 i
- // 同时最右面的奶牛受/不受限制
- signed main(){
- for(int i = 1; i <= n; i ++){
- for(int j = 1; j <= n; j ++){
- cin >> a[i][j];
- belong[i][a[i][j]] = j;
- }
- }
- f[0][0][0] = f[0][0][1] = 1;
- for(int i = 1; i <= n; i ++){
- f[1 << i - 1][i][0] = f[1 << i - 1][i][1] = 1;
- }
- int m = 1 << n;
- for(int i = 2; i <= n; i ++){
- for(int now = 0; now < m; now ++){
- if(__builtin_popcountll(now) == i){
- int p;
- for(int j = n; j >= 1; j --){
- if(now & (1 << j - 1)){
- p = j;
- break;
- }
- }
- // p 是二进制为 1 的索引最大的位置的索引
-
- // p 不动
- for(int j = 0; j <= n; j ++){
- f[now][p][0] += f[now ^ (1 << p - 1)][j][1];
- f[now][p][1] += f[now ^ (1 << p - 1)][j][1];
- }
- // j 到 p,同时在 j 位置上放 k
- for(int j = 1; j < p; j ++){
- if((now & (1 << j - 1)) && belong[p][j] < belong[p][p]){
- for(int k = 0; k <= n; k ++){
- if(belong[j][k] < belong[j][j]){
- f[now][j][1] += f[now ^ (1 << j - 1)][k][0];
- }
- }
- }
- if(now & (1 << j - 1)){
- for(int k = 0; k <= n; k ++){
- if(belong[j][k] < belong[j][j]){
- f[now][j][0] += f[now ^ (1 << j - 1)][k][0];
- }
- }
- }
- }
- }
- }
- }
- int q = mread();
- string s;
- while(q --){
- cin >> s;
- int tmp = 0;
- for(int i = 0; i < s.size(); i ++){
- if(s[i] == 'H'){
- tmp |= 1 << i;
- }
- }
- int ans1 = 0, ans2 = 0;
- for(int i = 0; i <= n; i ++){
- ans1 += f[tmp][i][1];
- ans2 += f[((1 << n) - 1) ^ tmp][i][1];
- }
- printf("%lld\n", ans1 * ans2);
- }
- return 0;
- }