题目
有3堆硬币,分别是3,4,5
二人轮流取硬币。
每人每次只能从某一堆上取任意数量。
不能弃权。
取到最后一枚硬币的为赢家。
求先取硬币一方有无必胜的招法。
分析:任何无偏博弈游戏都可以转换为尼姆堆 求解尼姆堆的方法为 将每个堆转换为二进制并且异或 如果结果为0则此时先手的必输。即当结果为0时为P态,否则为N态,我们的目标就是,判断现在是不是P态,如果是,则我们必输,如果不是,那我们把其从N态变为P态。变得方法就是让贡献最高位的数字变小使得结果为0.
例如 堆此时为2,5,12,14
分别转化为二进制 异或
0010
0101
1100
异或1110
---------------
0101
↑ 贡献最高位的那些数字就应该变小 使得结果为0 则对手输
结果 (2)101--->0 5变为0
(3)1100-->1001 12变为9
(4)1110-->1011 14变为11
代码中运用的方法为 a^b^c...==K 则K^a = b^c^....
public class _4_数学_03尼姆堆 {
static int[] arr = {2,5,12,14}; //尼姆堆
public static void nimu(int []arr)
{
int [] temp = new int[arr.length];
for(int i=0;i<arr.length;i++)
temp[i]=Integer.parseInt(Integer.toString(arr[i],2)); //依次将尼姆堆中的每个数据都转为2进制并存入temp
int x = 0; //异或结果
for(int i=0;i<arr.length;i++) //依次异或
x=x^arr[i];
System.out.println(Integer.toString(x,2)); //输出异或结果的二进制
for(int i=0;i<arr.length;i++)
{
if((x^arr[i])<arr[i]) //依次异或每个数,看是不是比原数字小
System.out.println(arr[i]+"--->"+Integer.toString(x^arr[i]));
//a^b^c^d = K 将b^c^d看作整体 是因为有了a才会使k不等于0 则如果a=k 则结果为0
}
}
public static void main(String[] args) {
nimu(arr);
}
}