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 种。

我们可以将每个状态抽象成节点,节点存下两个状态,改轮的操作者的状态和对方的状态。用有向边链接操作前的和操作后的情况。对于每个节点我们考虑其连向的所有节点:

  1. 若存在一个连向的节点的状态能够保证当前的后手必败,那么改轮的操作者必胜;
  2. 若其连向的所有节点都是必胜,该节点必败;
  3. 其余的情况,则是平局

可以反向建边然后跑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('
'))
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 }
View Code
原文地址:https://www.cnblogs.com/LQLlulu/p/8784944.html