HDU 3389 Game (阶梯博弈)
题意:
给你n个盒子,从1---n,你每次要找出来两个盒子下表分别是a,b;它们要满足(a+b)%2==1 && (a+b)%3==0,找到盒子之后要从b向a中拿过去至少1个卡牌
最多不限(这里b>a的)
阶梯博弈:(尼姆博弈升级)
这种题目就是只能从高出向低处放东西,谁最后一次放到最低处谁就获胜(比如本题就是从下标大的向下标小的位置放卡牌)
解法:
假设全部东西移到0这个位置就不能走了:
在偶数下标的阶梯是不影响的,因为最后全部东西肯定都移动到了0,而且0不是一个奇数,所以偶数下标移动东西是没有影响的
那么就只有奇数下标会造成影响,那么我们就可以对奇数下标的东西全部异或看他们是不是0就可以了
题目的终结点不一定就是0,这里只是举个例子(比如本题是把全部卡牌移动到1、3、4这三个位置之后就结束了)
我们做这样的题只需要找出来那个不影响题目,然后去判断其他影响题目的就可以了
参考题解:
1、3、4这3个下标的东西是不能移动的,例如
2-->1 5-->4 6-->3
这些盒子中卡片转移的步数的奇偶性是一定的。为什么这么说呢?
因为即使有些盒子例如编号11的盒子,有11->4和11->10->8->1两种选择,但是这两种选择的步数的奇偶性是相同的,都是奇数,所以奇偶性是一定的。
所以我们把这个阶梯博弈转化为尼姆博弈就行了,对步数为奇数的盒子进行尼姆博弈。在纸上多写几个数或者用打表的方法可以发现如下规律:
盒子编号模6为0,2,5的位置的移动步数为奇,其余为偶。
代码:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <iostream> 4 #include <string.h> 5 #include<math.h> 6 #include<set> 7 #include<map> 8 using namespace std; 9 const int maxn = 105; 10 const int INF=0x3f3f3f3f; 11 const int mod=1000000007; 12 typedef long long ll; 13 int main() 14 { 15 int t,cas=1; 16 scanf("%d",&t); 17 while(t--) 18 { 19 int n,m,flag=0; 20 scanf("%d",&n); 21 for(int i=1;i<=n;i++) 22 { 23 scanf("%d",&m); 24 if(i%6==2||i%6==5||i%6==0) 25 flag^=m; 26 } 27 if(flag) 28 printf("Case %d: Alice\n",cas++); 29 else 30 printf("Case %d: Bob\n",cas++); 31 } 32 return 0; 33 }