这场比赛实在北京camp期间打得,当时是说和室友一起开车。比赛开场我先交了C题,过了pretest后紧接着就被hack。发现坑点之后,告诉了室友,室友便开始了强盗生涯,怒hack近10发。
这场比赛让我发现:1. CF其实组队打也蛮好玩的,但是不太道德,以后我也尽量不会组队开车了; 2. 肯定是有很多组队上分选手存在的,而且组队上分非常高效;3. hack加的分可以远远超过一道题目的分,上分必学。
整体看这次题目还是比较简单的,都可以做。可惜最后一题一开始没有想清楚,忽略了策略图中的环,最后没能在赛中提交。
题目链接:http://codeforces.com/contest/919
A.
略
B. Perfect Numbers
题意:如果一个正整数各个数位之和为10,那么就称这个数是perfect的。让你找出第k(<= 10000)大的perfect数。
观察:猜测10000个perfect数不会很大,所以直接爆搜就好了。
方法:从1(或者19)开始向上枚举正整数,并且暴力判断。
code:略
思考:如果k很大(比如<= 1e18) 该怎么求呢?)
C. Seat Arrangements
题意:给你一个n*m的0/1矩阵,让你找同行或同列连续的k个0,问你有多少种方法。n,m,k <= 2000
观察:行和列可以分开做。好像滑动窗口,前缀和等等都可以做,需要注意的是k=1时,需要特判。
方法:二维前缀和/滑动窗口/多次一维前缀和
code:略
WA:没有考虑k=1的特殊情况。
D. Substring
题意:给你一个n个点,m条边的有向图,(n, m <= 3e5) 每个点标有一个字母。对于图中的一条路,它的权值是路径上出现次数最多的字母的个数。让你找出最大的权值。
观察:如果有环的话,那么最大的权值就是+inf。不然的话就是一个DAG上的DP。
方法:比赛里是先判环,然后倒着dp的。其实可以用正向拓扑排序,边dp,边判断是否有环。
code: 略
E. Congruence Equation
题意:看题吧。。
观察:p很小,不超过1e6+3,可以枚举的样子。然后既可以从p入手,考虑到a^x mod p 有周期T,且phi(p) = p-1是一个(也可以O(p-1)暴力的求出周期),而且p为素数,a%p != 0,则有a^(n+T) mod p == a^(n-T) mod p == a^n mod p == a^(n mod T) mod p,这里的减号是因为a mod p 有逆。于是我们可以枚举 n%T = r1, 然后可以得到n mod p == b*a^(-n) mod p。当n%T = r1确定了,a^(-n) 也就确定了,于是我们又有 n mod p == b*a^(-r) mod p。这样有关于n的两个线性模方程,直接求解即可。
方法:套中国剩余定理的板子
code:略
WA:在统计答案的时候,要小心0对答案的影响
F. A Game With Numbers
题意:看题吧。。
观察:其实一个人状态数很小,只有c(8+5-1, 5-1) = 495,即将八个相同的物品,分到五个不同的箱子的方法数,隔板法计算。所以两个人共同的状态不超过(495-1)*495(-1是因为保证先手手中一定有非0牌),就可以转化成一个有向图上的博弈。处理这种博弈一般的手段就是从结局出发,进行拓扑排序。如果一个状态为LOSE,那么到达它的状态均为WIN。如果一个状态所有后继都为WIN,那么它就是LOSE。剩下的状态都是DEAL。
方法:可能就是压缩状态麻烦了一点,其实很好写。
code:
1 /* 2 by skydog 3 */ 4 #include <iostream> 5 #include <cstdio> 6 #include <vector> 7 #include <utility> 8 #include <algorithm> 9 #include <cmath> 10 #include <cstring> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <deque> 16 #include <cassert> 17 18 using namespace std; 19 typedef long long ll; 20 typedef pair<int, int> ii; 21 typedef pair<ll, ll> l4; 22 23 #define mp make_pair 24 #define pb push_back 25 const int N = 4+1; 26 const int MAXCARD = 8+1; 27 const int MAXSTATE = 500; 28 int id[MAXCARD][MAXCARD][MAXCARD][MAXCARD][MAXCARD]; 29 int state[MAXSTATE][N]; 30 int sz; 31 int a[N]; 32 int &get_id(int *a) 33 { 34 return id[a[0]][a[1]][a[2]][a[3]][a[4]]; 35 } 36 void dfs(int pos, int left) 37 { 38 if (pos == N-1) 39 { 40 a[pos] = left; 41 get_id(a) = ++sz; 42 for (int i = 0; i < N; ++i) 43 state[sz][i] = a[i]; 44 return; 45 } 46 for (int i = 0; i <= left; ++i) 47 { 48 a[pos] = i; 49 dfs(pos+1, left-i); 50 } 51 } 52 53 bool win(int cur) 54 { 55 return state[cur][0] == MAXCARD-1; 56 } 57 int nxt_state(const int &cur, int prev, int tar) 58 { 59 memcpy(a, state[cur], sizeof(a)); 60 assert(a[prev]); 61 a[prev] -= 1; 62 a[tar] += 1; 63 return get_id(a); 64 } 65 vector<ii> g[MAXSTATE][MAXSTATE]; 66 int in[MAXSTATE][MAXSTATE]; 67 void build_state() 68 { 69 sz = 0; 70 dfs(0, 8); 71 cerr << "total state size = " << sz << endl; 72 } 73 int ans[MAXSTATE][MAXSTATE]; 74 const int WIN = 1, LOSE = 0, TIE = -1; 75 void build_graph() 76 { 77 for (int i = 1; i <= sz; ++i) 78 if (!win(i)) 79 for (int j = 1; j <= sz; ++j) 80 if (!win(j)) 81 { 82 for (int a = 1; a < N; ++a) if (state[i][a]) 83 for (int b = 1; b < N; ++b) if (state[j][b]) 84 { 85 int c = (a+b)%N; 86 int nxt = nxt_state(i, a, c); 87 g[j][nxt].pb(mp(i, j)); 88 ++in[i][j]; 89 } 90 91 } 92 queue<ii> q; 93 memset(ans, TIE, sizeof(ans)); 94 for (int i = 1; i <= sz; ++i) 95 if (!win(i)) 96 for (int j = 1; j <= sz; ++j) 97 { 98 assert((in[i][j]!=0)^win(j)); 99 if (!in[i][j]) 100 { 101 ans[i][j] = LOSE; 102 q.push(mp(i, j)); 103 } 104 } 105 while (!q.empty()) 106 { 107 ii cur = q.front(); 108 q.pop(); 109 int cur_ans = ans[cur.first][cur.second]; 110 for (auto pr : g[cur.first][cur.second]) 111 { 112 int &nxt_ans = ans[pr.first][pr.second]; 113 if (nxt_ans != TIE) 114 continue; 115 if (cur_ans == LOSE) 116 { 117 nxt_ans = WIN; 118 q.push(pr); 119 } 120 else 121 { 122 int &nxt_in = in[pr.first][pr.second]; 123 --nxt_in; 124 if (nxt_in == 0) 125 { 126 nxt_ans = LOSE; 127 q.push(pr); 128 } 129 } 130 } 131 } 132 } 133 int read() 134 { 135 memset(a, 0, sizeof(a)); 136 for (int i = 1; i < MAXCARD; ++i) 137 { 138 int x; 139 scanf("%d", &x); 140 ++a[x]; 141 } 142 return get_id(a); 143 } 144 int main() 145 { 146 build_state(); 147 build_graph(); 148 int T; 149 scanf("%d", &T); 150 for (int kase = 1; kase <= T; ++kase) 151 { 152 int f; 153 scanf("%d", &f); 154 int a = read(), b = read(); 155 if (f) 156 swap(a, b); 157 int ret = ans[a][b]; 158 if (ret == TIE) 159 puts("Deal"); 160 else 161 puts(ret^f?"Alice":"Bob"); 162 } 163 }