[CSAcademy]A-Game

题目大意:
  给你一个只含字符'A'和'B'的串,A和B两人轮流对其中的子串染色,要求被染色的子串中不包含已经被染色的子串。
  最后,如果一方染的'A'少,那么这一方胜;
  如果双方染的'A'和'B'一样多,那么就是平局。
  问哪一方有必胜策略,或是都没有必胜策略。

思路:
  首先可以想到一个贪心的做法:
  当字符串中还有'B'的时候,取一段全'B'子串;
  当字符串中只剩下'A'的时候,不得不取'A',这时候双方轮流取一个。
  显然,当'A'的数量为偶数时,由于双方都轮流取一个'A',最后双方取的'A'一样多,那么一定是平局。
  当'A'的数量为奇数时,显然有一方会多取一个'A',而且一定是先开始取'A'的一方输。
  那么问题就转化成了如果只取'B',最后不能取的一方输(因为只能取'A'了)。
  这就变成了一个经典的Nim游戏模型。
  我们把每一段连续的'B'当作一个子游戏,把'B'的数量当作游戏的状态。
  对于一个状态x,sg(x)=mex{sg(y)|y是x的后继状态}。
  显然,由于题目没有特殊的限制,x的后继状态总是0~x-1的所有状态。
  那么显然sg(x)=x。

 1 #include<cstdio>
 2 #include<cctype>
 3 inline int getint() {
 4     register char ch;
 5     while(!isdigit(ch=getchar()));
 6     register int x=ch^'0';
 7     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 8     return x;
 9 }
10 inline char getupper() {
11     register char ch;
12     while(!isupper(ch=getchar()));
13     return ch;
14 }
15 inline int getsg(const int &x) {
16     return x;
17 }
18 int main() {
19     int n=getint();
20     int tota=0,ans=0,cnt=0;
21     for(int i=1,ch='\0',last;i<=n;i++) {
22         last=ch;
23         ch=getupper();
24         if(ch=='A') {
25             tota++;
26             if(last=='B') {
27                 ans^=getsg(cnt);
28                 cnt=0;
29             }
30         } else {
31             cnt++;
32         }
33     }
34     ans^=getsg(cnt);
35     if(tota&1) {
36         puts(ans?"A":"B");
37     } else {
38         puts("-1");
39     }
40     return 0;
41 }

 

posted @ 2017-09-30 09:05  skylee03  阅读(207)  评论(0编辑  收藏  举报