Codeforces 919F——A Game With Numbers
转自大佬博客:https://www.cnblogs.com/NaVi-Awson/p/8405966.html ;
题意
两个人 Van♂ 游戏,每人手上各有 8'>88 张牌,牌上数字均为 [0,4]'>[0,4][0,4] 之间的数。每个人在自己的回合选自己手牌中数字不为 0'>00的一张与对方手牌中不为 0'>00 的一张。数字相加对 5'>55 取模,赋给自己当前选中的这张牌。 T'>TT 组询问,给出先手,问谁能胜。
分析
首先注意到卡牌顺序是没有影响的,我们可以按数字大小排序。这时由可重复的组合得每个人可能的方案只有 495(8+5−18)=495 种。所以两个人不同的状态共 4952=2450254952=245025 种。
我们可以将每个状态抽象成节点,节点存下两个状态,改轮的操作者的状态和对方的状态。用有向边链接操作前的和操作后的情况。对于每个节点我们考虑其连向的所有节点:
- 若存在一个连向的节点的状态能够保证当前的后手必败,那么改轮的操作者必胜;
- 若其连向的所有节点都是必胜,该节点必败;
- 其余的情况,则是平局
可以反向建边然后跑topsort
PS:我会说大佬这篇博客让我的编码状态姿势大幅度提高了吗~
1 //It is made by Awson on 2018.2.2 2 #include <bits/stdc++.h> 3 #define LL long long 4 #define dob complex<double> 5 #define Abs(a) ((a) < 0 ? (-(a)) : (a)) 6 #define Max(a, b) ((a) > (b) ? (a) : (b)) 7 #define Min(a, b) ((a) < (b) ? (a) : (b)) 8 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) 9 #define writeln(x) (write(x), putchar('\n')) 10 #define lowbit(x) ((x)&(-(x))) 11 using namespace std; 12 const int N = 400000; 13 void read(int &x) { 14 char ch; bool flag = 0; 15 for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); 16 for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); 17 x *= 1-2*flag; 18 } 19 void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); } 20 void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } 21 22 int S[N+5], C[N+5], cnt; 23 struct hs { 24 int a[8]; 25 hs() {memset(a, 0, sizeof(a)); } 26 hs(int x) {for (int i = 7; i >= 0; i--) a[i] = x%5, x /= 5; } 27 hs(int *_a) {for (int i = 0; i < 8; i++) a[i] = _a[i]; } 28 void rd() {for (int i = 0; i < 8; i++) read(a[i]); } 29 void st() {sort(a, a+8); } 30 int hash() { 31 int ans = 0; 32 for (int i = 0; i < 8; i++) ans = ans*5+a[i]; 33 return ans; 34 } 35 }; 36 struct tt {int to, next; }edge[(N<<6)+5]; 37 int path[N+5], top, in[N+5], ans[N+5]; 38 39 void add(int u, int v) {++in[v]; edge[++top].to = v, edge[top].next = path[u]; path[u] = top; } 40 int no(int a, int b) {return (a-1)*cnt+b-1; } 41 void dfs(int cen, int last, int h) { 42 if (cen == 8) {S[++cnt] = h, C[h] = cnt; return; } 43 for (int i = last; i < 5; i++) dfs(cen+1, i, h*5+i); 44 } 45 void prework() { 46 dfs(0, 0, 0); 47 for (int i = 1; i <= cnt; i++) 48 for (int j = 1; j <= cnt; j++) { 49 hs a(S[i]), b(S[j]); 50 for (int p = 0; p < 8; p++) if (a.a[p]) 51 for (int q = 0; q < 8; q++) if (b.a[q]) { 52 hs c(a.a); 53 c.a[p] = (a.a[p]+b.a[q])%5; 54 c.st(); int tmp = C[c.hash()]; 55 add(no(j, tmp), no(i, j)); 56 } 57 } 58 queue<int>Q; while (!Q.empty()) Q.pop(); 59 for (int i = 2; i <= cnt; i++) ans[no(i, 1)] = 1, Q.push(no(i, 1)); 60 while (!Q.empty()) { 61 int u = Q.front(); Q.pop(); 62 for (int i = path[u]; i; i = edge[i].next) if (!ans[edge[i].to]) { 63 if (ans[u] == 1) {ans[edge[i].to] = -1; Q.push(edge[i].to); } 64 else if (--in[edge[i].to] == 0) { 65 Q.push(edge[i].to); ans[edge[i].to] = 1; 66 } 67 } 68 } 69 } 70 void work() { 71 prework(); 72 int t, f; hs a, b; read(t); 73 while (t--) { 74 read(f); a.rd(), b.rd(); a.st(); b.st(); 75 if (f) swap(a, b); 76 int as = ans[no(C[a.hash()], C[b.hash()])]; 77 if (as == 0) puts("Deal"); 78 else if (as == -1 && f || as == 1 && !f) puts("Bob"); 79 else puts("Alice"); 80 } 81 } 82 int main() { 83 work(); 84 return 0; 85 }