比赛 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;
}