大概看了一种博弈问题的变化题,左边这个链接讲解的还是不错的。
Nim博弈大家都知道,就是有N堆石子,两人轮流取,每次在一堆中取任意个,取到最后一个的胜利。
现在的变化是,取到最后一个的算失败。
这怎么做?
首先我们定义:
对于N堆石子,每堆的个数为Ai(1<=i<=N)。
设C=A1^A2^...^An;
若C=0,则状态设为T,称为利他态。反之,设状态为S,称为利己态。
孤单堆,该堆的石子数量为1.
充裕堆,该堆的石子数量大于1.
在T态中,T2为充裕堆数量>1,T0为充裕堆数量为0.(T1不存在)。
在S态中,S2为充裕堆数量>1,S1为充裕堆数量为1,S0为充裕堆数量为0;
定理1:T0为必胜态。
由于仅存在孤单堆,且C=0,即有偶数个孤单堆,故为必胜点。反之S0为必败点。
定理2:S1为必胜态。
有且仅有一个充裕堆,则,若有奇数个孤单堆,则将此充裕堆取完,则对方面临S0态,必败,故此法可取胜。
若有偶数个孤单堆,则将此充裕堆取成孤单堆,对方仍旧面临S0态,故此法仍胜。
定理3:T2只能转化为S2或S1。
首先T态必须变为S态,充裕堆不能一次由2变为0,故不能变为S0,得证。
定理4:S2不能一次转化为T0。
定理5:S2可以一次转化为T2。
由于C的最高位为1,则取Ai中同最高位的At。
设x=At^C。则
A1^A2^....^x^...^An=
A1^A2^....^At^C^...^An=
A1^A2^....^An^A1^A2^...^An=0;为T态.
定理6:S2采取合理的措施,必胜。
任意S2都可以转化为T2,T2能转化为S1或S2。这样逼迫队手由T2转S1,抱持必胜态。
故整个状态变换为:
(T2->)S2->T2->S2->.....->T2->S1->T0->S0->....->T0;
#include<iostream> using namespace std; int main() { int T; scanf( "%d",&T ); while( T-- ) { int n; scanf( "%d",&n ); int rec[50]; int sin=0,mul=0,xo=0; for( int i=0;i<n;i++ ) { scanf( "%d",&rec[i] ); rec[i]>1?mul++:sin++; xo^=rec[i]; } if( (mul==1) || (mul==0&&xo==0) || (mul>1&&xo) ) printf( "John\n" ); else printf( "Brother\n" ); } return 0; }