Codeforces Round #460 (Div 2)

这场比赛实在北京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 }
View Code

 

posted @ 2018-02-07 01:13  大四开始ACM  阅读(188)  评论(0编辑  收藏  举报