TC SRM 637 DIV1 500 PathGame

Problem Statement

给一个2*1000的board,每个格子黑或者白。白格子从左到右连成一条连接第一列和最后一列的path,path上相邻两格有公共边。两人轮流把白格子涂成黑格子,最后一个被迫涂黑格子使path断开的人输。问先手必胜还是必败。

(Translated By myq_952)

Tutorial

做sg的题有点生(有什么生不生的不就dp嘛)

考虑以一段2*k的全白矩形作为局面,涂黑一个格子会把原局面拆成两个后继局面,然后$n^2$求局面的sg即可

要注意的是,因为本题局面是否合法还和两侧的出口情况有关,所以要分4类讨论(见代码)

另外,既然已以无路可走作为必败态,那么非法局面的sg值就没有意义,要忽略掉==这很重要

我在做的时候,用时间标记的同时调用了其他同样会更新时间标记的函数,导致之间时间标记无效了==这很蒟蒻

  1 #include <set>
  2 #include <ctime>
  3 #include <queue>
  4 #include <cstdio>
  5 #include <bitset>
  6 #include <cctype>
  7 #include <bitset>
  8 #include <cstdlib>
  9 #include <cassert>
 10 #include <cstring>
 11 #include <iostream>
 12 #include <algorithm>
 13 #define inf (1<<30)
 14 #define INF (1ll<<62)
 15 #define fi first
 16 #define se second
 17 #define rep(x,s,t) for(register int x=s,t_=t;x<t_;++x)
 18 #define per(x,s,t) for(register int x=t-1,s_=s;x>=s_;--x)
 19 #define travel(x) for(int I=last[x],to;I&&(to=e[I].to);I=e[I].nxt)
 20 #define prt(x) cout<<#x<<":"<<x<<" "
 21 #define prtn(x) cout<<#x<<":"<<x<<endl
 22 #define pb(x) push_back(x)
 23 #define hash asfmaljkg
 24 #define rank asfjhgskjf
 25 #define y1 asggnja
 26 #define y2 slfvm
 27 using namespace std;
 28 typedef long long ll;
 29 typedef pair<int,int> ii;
 30
 31 string WIN="Snuke";
 32 string LOSE="Sothe";
 33
 34 const int maxn=1024;
 35 int n;
 36 int mark[maxn],allc;
 37 struct SG_CIRCLE{
 38     int sg[4][maxn];
 39     void init(){
 40         memset(sg[0],-1,n+1<<2);
 41         memset(sg[1],-1,n+1<<2);
 42         memset(sg[2],-1,n+1<<2);
 43         memset(sg[3],-1,n+1<<2);
 44     }
 45     int sg0(int x){
 46         if(~sg[0][x])return sg[0][x];
 47         if(x<=1)return sg[0][x]=x;
 48
 49         rep(i,0,x)sg1(i);
 50
 51         ++allc;
 52         rep(i,0,x)mark[sg1(i)^sg1(x-i-1)]=allc;
 53         rep(i,0,maxn)if(mark[i]!=allc)
 54             return sg[0][x]=i;
 55     }
 56     //....
 57     //....
 58     int sg1(int x){
 59         if(~sg[1][x])return sg[1][x];
 60         if(x<=1)return sg[1][x]=x;
 61
 62         rep(i,0,x)sg1(i),sg2(i),sg3(i);
 63
 64         ++allc;
 65         rep(i,1,x+1){
 66             if(x-i)mark[sg1(i-1)^sg2(x-i)]=allc;
 67             mark[sg1(i-1)^sg3(x-i)]=allc;
 68         }
 69         rep(i,0,maxn)if(mark[i]!=allc)
 70             return sg[1][x]=i;
 71     }
 72     //#...
 73     //....
 74     int sg2(int x){
 75         if(~sg[2][x])return sg[2][x];
 76         if(x<=1)return sg[2][x]=0;///不管有没有都输
 77
 78         rep(i,0,x)sg2(i),sg3(i);
 79
 80         ++allc;
 81         rep(i,2,x+1)mark[sg2(i-1)^sg3(x-i)]=allc;
 82         rep(i,0,maxn)if(mark[i]!=allc)
 83             return sg[2][x]=i;
 84     }
 85     //#...
 86     //...#
 87     int sg3(int x){
 88         if(~sg[3][x])return sg[3][x];
 89         if(x<=1)return sg[3][x]=x;
 90
 91         rep(i,0,x)sg2(i),sg3(i);
 92
 93         ++allc;
 94         rep(i,1,x+1){
 95             if(i-1&&x-i)mark[sg2(i-1)^sg2(x-i)]=allc;
 96             mark[sg3(i-1)^sg3(x-i)]=allc;
 97         }
 98         rep(i,0,maxn)if(mark[i]!=allc)
 99             return sg[3][x]=i;
100     }
101     //#..#
102     //....
103 }SG;
104 class PathGame {
105 public:
106     string judge(vector <string> d) {
107         n=d[0].length();
108
109         SG.init();
110         int ans=0;
111         for(int i=0,j;i<n;i++){
112             for(j=i;j<n&&d[0][j]==‘.‘&&d[1][j]==‘.‘;j++);
113             if(j==i)continue;
114             if(i==0&&j==n)ans^=SG.sg0(j-i);
115             else if(i==0||j==n)ans^=SG.sg1(j-i);
116             else if(d[0][i-1]^d[0][j])ans^=SG.sg2(j-i);
117             else ans^=SG.sg3(j-i);
118             i=j;
119         }
120
121         return ans?WIN:LOSE;
122     }
123 };
时间: 2025-01-02 14:38:28

TC SRM 637 DIV1 500 PathGame的相关文章

SRM 618 DIV1 500

非常棒的组合问题,看了好一会,无想法.... 有很多做法,我发现不考虑顺序的最好理解,也最好写. 结果一定是两种形式 A....A   dp[n-1] A...A...A sgma(dp[j]*dp[n-j-1])( 1<=j<=n-2) 最后乘上n! 什么时候才能自己在比赛中做出一个500分来啊!!! class LongWordsDiv1 { public : int count(int n) { int i,j; fact[0] = 1; for(i = 1; i <= n; i

[TC SRM 697 div1 lev1] DivisibleSetDiv1

Tutorial:https://apps.topcoder.com/wiki/display/tc/SRM+697#DivisibleSetDiv1 Note:证明过程值得一看. 主要内容:寻找[x1,x2,...,xn]使得满足bi * xi >= S - xi,其中S = x1 + x2 + ... + xn.

TC SRM 655 DIV1 250,500pt

250: 给一个n*n的格子图,每个格子颜色为白色或者红色.假设刚开始都是白色,每次可以涂k*k的一块正方形格子区域,涂成红色或白色,后面涂的可以覆盖前面涂的.给你最终状态,问从初始状态涂任意次数,可不可以涂成最终状态. 挺不错的题,感觉比500有意思.刚开始想简单了,就从前往后枚举,碰到跟最终状态不同就涂.很显然错了.其实实质还是贪心,因为后涂的覆盖前面涂的,所以从最后开始考虑,每次选一块完整颜色相同的出来,涂成该颜色,然后以后该区域的颜色就不会变了,这样贪心的每次选一块可以涂的区域出来,直到

TC SRM 638 DIV1 600 NarrowPassage2

Problem Statement 在一个狭长的通道中有$n$只狼,每只狼的体积为$size_i$,如果相邻的两只狼体积不超过$m$,则可以交换位置,求可以有多少种排列. $n≤50,1≤m≤1,000,000,000$ Tutorial 每次选出区间中体积最大的狼,如果其他狼可以越过它,那么即可在整个区间里自由移动,而不能越过它的狼则被隔离到两个区间里,可以分治. 区间总共有$n$只狼,能自由移动的狼个数为$cnt$,那么最后结果等于$$solve(l)*solve(r)*A_{n}^{cnt

tc srm 636 div2 500

100的数据直接暴力就行,想多了... ac的代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <algorithm> 7 #include <vector> 8 #define LL __int64 9 const int maxn =

[TC SRM 662 div1 lev1] FoxesOfTheRoundTable

转载:http://codeforces.com/blog/entry/19151 Note: 将问题转化为寻找hamiltonian回路问题.证明过程值得一看. Suppose the heights are sorted: h[0] <= h[1] <= h[2] ... In one hand, we know the answer can't be smaller than max{x[i+2] — x[i]}. We can proof this in the following w

Topcoder SRM 655 DIV1 500 FoldingPaper2 递归 + 枚举

题意:给你一张长W,宽H 的纸,问你能不能者成给定的大小, 每一次折纸只能折成整数大小. 解题思路:递推+枚举   枚举给定大小的长和宽,然后套进 W,H中求最小值  , 折纸策略最优是每次折半. 解题代码: 1 // BEGIN CUT HERE 2 /* 3 4 */ 5 // END CUT HERE 6 #line 7 "FoldingPaper2.cpp" 7 #include <cstdlib> 8 #include <cctype> 9 #incl

Topcoder SRM 563 Div1 500 SpellCards

题意 [题目链接]这怎么发链接啊..... 有\(n\)张符卡排成一个队列,每张符卡有两个属性,等级\(li\)和伤害\(di\). 你可以做任意次操作,每次操作为以下二者之一: 把队首的符卡移动到队尾. 使用队首的符卡,对敌人造成\(d_i\)点伤害,并丢弃队首的\(l_i\)张符卡(包括你所使用的符卡).如果队列不足\(l_i\)张符卡那么你不能使用. 求出造成的伤害的总和的最大值. \(1<=n<=50, 1<=li<=50, 1<=di<=10000\) Sol

TC srm 673 300 div1

TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能够组成一个骑兵,这个骑兵的战斗力等于马的战斗力乘以人的战斗力,问你有多少种组合方式满足其他骑兵的战斗力都不超过第0号骑兵. Input Output Sample Input Sample Output HINT 题意 题解: 大概就暴力枚举哪匹马和第0号人匹配,后面的骑兵我们按照战斗力从大到小排序之后,