比赛 round 2『计协冻梨桐难霍』 评测结果 AAAAAAAAAAAAAAAAAA
题目名称 交换礼物 最终得分 100
用户昵称 darkMoon 运行时间 3.748 s
代码语言 C++ 内存使用 36.86 MiB
提交时间 2024-11-22 08:17:21
显示代码纯文本
  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. auto mread = [](){int x;scanf("%lld", &x);return x;};
  5. const int N = 25, M = 270005;
  6. int n = mread(), a[N][N], belong[N][N], f[M][N][2];
  7. // f_now_i 表示 now 状态里面的礼物可以重新分配,可分配的奶牛中最靠右的奶牛分到的礼物是 i
  8. // 同时最右面的奶牛受/不受限制
  9. signed main(){
  10. for(int i = 1; i <= n; i ++){
  11. for(int j = 1; j <= n; j ++){
  12. cin >> a[i][j];
  13. belong[i][a[i][j]] = j;
  14. }
  15. }
  16. f[0][0][0] = f[0][0][1] = 1;
  17. for(int i = 1; i <= n; i ++){
  18. f[1 << i - 1][i][0] = f[1 << i - 1][i][1] = 1;
  19. }
  20. int m = 1 << n;
  21. for(int i = 2; i <= n; i ++){
  22. for(int now = 0; now < m; now ++){
  23. if(__builtin_popcountll(now) == i){
  24. int p;
  25. for(int j = n; j >= 1; j --){
  26. if(now & (1 << j - 1)){
  27. p = j;
  28. break;
  29. }
  30. }
  31. // p 是二进制为 1 的索引最大的位置的索引
  32.  
  33. // p 不动
  34. for(int j = 0; j <= n; j ++){
  35. f[now][p][0] += f[now ^ (1 << p - 1)][j][1];
  36. f[now][p][1] += f[now ^ (1 << p - 1)][j][1];
  37. }
  38. // j 到 p,同时在 j 位置上放 k
  39. for(int j = 1; j < p; j ++){
  40. if((now & (1 << j - 1)) && belong[p][j] < belong[p][p]){
  41. for(int k = 0; k <= n; k ++){
  42. if(belong[j][k] < belong[j][j]){
  43. f[now][j][1] += f[now ^ (1 << j - 1)][k][0];
  44. }
  45. }
  46. }
  47. if(now & (1 << j - 1)){
  48. for(int k = 0; k <= n; k ++){
  49. if(belong[j][k] < belong[j][j]){
  50. f[now][j][0] += f[now ^ (1 << j - 1)][k][0];
  51. }
  52. }
  53. }
  54. }
  55. }
  56. }
  57. }
  58. int q = mread();
  59. string s;
  60. while(q --){
  61. cin >> s;
  62. int tmp = 0;
  63. for(int i = 0; i < s.size(); i ++){
  64. if(s[i] == 'H'){
  65. tmp |= 1 << i;
  66. }
  67. }
  68. int ans1 = 0, ans2 = 0;
  69. for(int i = 0; i <= n; i ++){
  70. ans1 += f[tmp][i][1];
  71. ans2 += f[((1 << n) - 1) ^ tmp][i][1];
  72. }
  73. printf("%lld\n", ans1 * ans2);
  74. }
  75. return 0;
  76. }