Bash游戏(同余):

有一堆石子共有N个。A B两个人轮流拿,A先拿。每次最少拿1颗,最多拿K颗,拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出N和K,问最后谁能赢得比赛。

小学的时候沉迷的游戏…

如果n可以整除k+1的话,B有必胜策略,只要报k+1-A报的数就可以了。

如果不整除的话,由于A先手,所以A就胜了。

Nim游戏(异或):

有N堆石子。A B两个人轮流拿,A先拿。每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出N及每堆石子的数量,问最后谁能赢得比赛。

如果把n堆抽象为n个非负整数,再将n个整数转化为二进制,然后对n个二进制数按位相加(不进位),若每一位相加都为偶数,那么称这个状态为偶状态,否则称它为奇状态.

事实一:假设轮到你行动了,这时堆里的Nim和为0。这样不管你怎么做,你动作后的Nim和不会等于0.

事实二:假设轮到你行动了,这时堆里的Nim和不为0。但是可以保证的是,存在一种取法能在你行动后的堆的Nim和为0。

现在如果你是玩家A,所以你先走。接着假设现在堆里的Nim和不等于0.你的策略将会是这样:如果可能尽可能使得下一个Nim和,也就是你动作后的Nim和为0.这也意味着无论B如何动作通过事实1可知,B的这个动作会把下个Nim和变得不为0.

让我们开始,在表中记录每一步的Nim和:

下一个要走的玩家 Nim和 能否变为0? 下个Nim和
A 非0 0
B 0 非0
A 非0 0
B 0 非0
A 非0 0
……

这个像乒乓球一样的Nim和不断在0和非0之间转化,意味着你保证能赢!如果B注定要赢,她将要把最后一个硬币攒在手中。也就是说:她需要一个动作来产生零Nim和,但在我们看来这是不可能的。你的每次动作,都在把Nim和减少到0。当游戏进行到快到结尾时时,零Nim和就等价于没有一个硬币剩余——这时你就赢了。

那么对于n堆物品,只要判断它是否是奇状态就可以判断是否先手有必赢策略.

以非零Nim和打头的游戏,玩家A都有一个必胜策略。策略就是在每一步都让下一个Nim和减少到0.

如果游戏开始时为零Nim和,那么玩家B有一个必胜策略。当轮到B动作时不管玩家A在第一步做了什么将会留下一个非零Nim和。那么按同上的理由,必胜策略掌握在了B的手中。

但是求每个数的二进制表示略显麻烦,可以用位运算.

XOR 和判断: 如果有奇数个二进制数在第K位为1 那么在这一位上的和为奇,同样的,偶数个1和为偶.

很明显位运算xor满足我们的要求,偶数个1异或和为0,奇数个为1。

当这些数都做异或运算时等于0时,先手输,否则后手输。

如果Nim游戏中的规则稍微变动一下,每次最多只能取K个,怎么处理?

方法是将每堆石子数mod (k+1).

int main()
{
    int t,n,k,sum=0,ch;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&ch);
        sum=sum^ch;
    }
    if(sum==0)printf("B\n");
    else printf("A\n");
    return 0;
}
反Nim游戏:

在反尼姆博奕中判断必胜局面的条件有两点,满足任意一点先手都能取胜,即必胜局面。

1:各堆石子数目异或结果不等于0,且存在有石子数目大于1的石子堆。

2:各堆石子数目异或结果等于0,且所有石子堆数目全部为1。

Wythoff游戏(黄金分割):

有两堆各若干的物品,两人轮流从其中一堆取至少一件物品,至多不限,或从两堆中同时取相同件物品,规定最后取完者胜利。

这种情况下是颇为复杂的。我们用(ak,bk)(ak ≤ bk ,k=0,1,2,…,n)表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势(先手必败)。前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。

可以看出,a0=b0=0,ak是未在前面出现过的最小自然数,而 bk= ak + k。

若两堆物品的初始值为(x,y),且x<y,则另z=y-x;记w=(int)[((sqrt(5)+1)/2)*z ];若w=x,则先手必败,否则先手必胜。

给你一个局面,让你求先手输赢,假设先手赢的话输出他第一次的取法。

​ 首先讨论在两边同时取的情况,很明显两边同时取的话,不论怎样取他的差值是不会变的,那么我们可以根据差值计算出其中的小的值,然后加上差值就是大的一个值,当

然能取的条件是求出的最小的值不能大于其中小的一堆的石子数目。

​ 加入在一堆中取的话,可以取任意一堆,那么其差值也是不定的,但是我们可以枚举差值,差值范围是0 —- 大的石子数目,然后根据上面的理论判断满足条件的话就是一种合理的取法。

int main()
{
    int a,b;
    while(scanf("%d%d",&a,&b)!=EOF)
    {
        if(a==0&&b==0)break;
        if(a>b)swap(a,b);
        int d=b-a;
        int x=(int)((sqrt(5)+1)/2*d);//这里注意!
        if(x==a)printf("0\n");
        else
        {
            printf("1\n");
            int ans1,ans2;
            if(a>x)
            {
                ans1=x;
                ans2=b-a+x;
                printf("%d %d\n",ans1,ans2);
            }
            for(int i=1;i<=b;i++)
            {
                ans1=a;ans2=b-i;
                if(ans1>ans2)swap(ans1,ans2);
                d=ans2-ans1;
                x=(int)((sqrt(5)+1)/2*d);
                if(x==ans1)
                    printf("%d %d\n",ans1,ans2);
            }
            if(a!=b)//如果a和b相同的话在a堆取和在b堆取是一样的
            {
                for(int i=1;i<=a;i++)
                {
                    ans1=a-i;ans2=b;
                    if(ans1>ans2)swap(ans1,ans2);
                    d=ans2-ans1;
                    x=(int)((sqrt(5)+1)/2*d);
                    if(x==ans1)
                        printf("%d %d\n",ans1,ans2);
                }
            }
        }
    }
    return 0;
}
斐波那契博弈(找规律):

1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍。取完者胜。

n = 2时输出second;
n = 3时也是输出second;
n = 4时,第一个人想获胜就必须先拿1个,这时剩余的石子数为3,此时无论第二个人如何取,第一个人都能赢,输出first;
n = 5时,first不可能获胜,因为他取2时,second直接取掉剩下的3个就会获胜,当他取1时,这样就变成了n为4的情形,所以输出的是second;
n = 6时,first只要去掉1个,就可以让局势变成n为5的情形,所以输出的是first; n = 7时,first取掉2个,局势变成n为5的情形,故first赢,所以输出的是first;
n = 8时,当first取1的时候,局势变为7的情形,第二个人可赢,first取2的时候,局势变成n为6得到情形,也是第二个人赢,取3的时候,second直接取掉剩下的5个,所以n = 8时,输出的是second;
…………
从上面的分析可以看出,n为2、3、5、8时,这些都是输出second,即必败点,仔细的人会发现这些满足斐波那契数的规律,可以推断13也是一个必败点。
借助“Zeckendorf定理”(齐肯多夫定理):任何正整数可以表示为若干个不连续的Fibonacci数之和。n=12时,只要谁能使石子剩下8且此次取子没超过3就能获胜。因此可以把12看成8+4,把8看成一个站,等价与对4进行”气喘操作”。又如13,13=8+5,5本来就是必败态,得出13也是必败态。也就是说,只要是斐波那契数,都是必败点。

先手胜当且仅当n不是斐波那契数(n为物品总数)


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

高精度和低精度的乘除法&&大数取模 Previous
二进制相关 Next