Alice and Bob

Alice and Bob

题意:

两人博弈,每次一个人从一堆中拿k个,同时从另一堆拿k * s(s>=0)个,问谁先不能拿
10000组数据,N<=5000

题解:

(x,y)表示第一堆石头数量为x,第二堆为y
如果(x,y)是必败状态,那么通过取走石头一次直接形成(x,y)的(x1,y1)必然不是必败状态

如果(x,y)不是必败状态,那(x1,y1)就不一定了
可以通过反证去理解
指向必败状态的是必胜状态,必胜状态可以指向必败,也可以指向必胜。必败状态无法到必败状态

综上:我们只需要关注一个点是否可以由必败点得到,如果可以,该点不是必败点,否则是必败点

此时复杂度为O(n4),但是要知道一个结论:对于一个的i只存在至多一种j后手能够获胜
证明如下:
若存在(i,q)(i,p)(p>q)满足后手胜,那么Alice只需将(i,p)->(i,q)即可获胜,不满足后手胜的条件。
这样复杂度就大约在O(n3)

代码:

#include<iostream>
#include<stdio.h>
using namespace std;
bool f[5001][5001];
int main()
{    
    for(int i=0;i<=5000;i++)//自小到大枚举i,j
    for(int j=0;j<=5000;j++)
    {
        if(f[i][j]==0)//对于每种必败态进行拓展
        {
            for(int k=1;k+i<=5000;k++)for(int s=0;s*k+j<=5000;s++)f[i+k][j+s*k]=1;
            for(int k=1;k+j<=5000;k++)for(int s=0;s*k+i<=5000;s++)f[i+s*k][j+k]=1;
        }
    }
    int t,n,m;
    cin>>t;
    while(t--)
    {
       scanf("%d%d",&n,&m);
        if(f[n][m]==0)
        {
            puts("Bob");
        }
        else 
            puts("Alice");
     }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值