巴什博弈

题目描述

简易版本

两个顶尖聪明的人在玩游戏,有n个石子,每人可以随便拿1~m个石子,不能拿的人为败者,问谁会胜利

  • 如果n∈[1,m],先手必胜
  • n == m+1,先手必败。推广可知 n==k(m+1)时先手必败
  • n == k(m+1)+r,先手必胜。先手拿去r个,后手拿去x个,先手之后拿去 m+1-x个即可将局势转变为第二种情况,取胜。
    简而言之就是面临 n % (m+1) == 0的人必败。
#include<cstdio>
int main()
{
   int n,m;
   scanf("%d%d",&n,&m);
   if(n % (m+1) !=0) printf("first win");
   else printf("second win");
   return  0;
}

例题
POJ2368

有K(K∈[3,100 000 000 ])个石子,每次最多取L个,确定L(2 <= L < K)使得后手胜利。
那么我们就要让先手面临 K % (L+1) == 0的局势,找出K的因子中大于2的减一就是所求L。注意求因子的过程不能枚举,会TLE。

#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int main(){
    int sp[10010];
    int n;
    while(scanf("%d",&n) != EOF){
        int ans = 1;
        int size = 0;
        for(int i = 1; i * i<= n;++i){
            if(n % i == 0){
                sp[size++] = i;
                sp[size++] = n / i;
            }
        }
        sort(sp,sp + size);
        for(int i = 0;i < size;++i){
            if(sp[i] > 2){
                ans = sp[i];
                break;
            }
        }

        printf("%d\n",ans-1);
    }

    return 0;
}

升级版

有三个数字n,p,q,表示一堆硬币一共有n枚,从这个硬币堆里取硬币,一次最少取p枚,最多q枚,如果剩下少于p枚就要一次取完。两人轮流取,直到堆里的硬币取完,最后一次取硬币的算输。
分两种大情况:

  • n % (p + q) == 0,先手必胜。先手取q个,后手取m个,先手之后取p+q-m个,最后留给后手的剩下p个,只能一次性全取光。
  • n %(p+q) == s
    s 范围结果(胜利)取胜步骤剩余备注
    1<=s<=p后手先手取m个,后手取p+q-m个留给先手s个
    p<s<=q先手先手取t个,使得1<= s-t <=p,后手取m个,先手取p+q-m个留给后手s-t个即转换为情况2.1
    q<s<=p+q先手先手取q个,余数s<p,后手取m,先手取p+q-m留给后手m即转换为情况2.1

以上可知,面临的局势的余数在1-p中的人必输。

#include <iostream>  
#include <cstdio>  
using namespace std;  
int main()  
{  
    int n, p, q;  
    while(~scanf("%d%d%d",&n, &p, &q))  
    {  
        if(n % (p+q) <= p && n % (p+q) >= 1)  
            printf("LOST\n");  
        else  
            printf("WIN\n");  
    }  
    return 0;  
}
``
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值