0
点赞
收藏
分享

微信扫一扫

HDU 2149 Public Sale(巴什博奕)

搬砖的小木匠 2022-08-04 阅读 54


题目地址:​​点击打开链接​​

思路:

一.巴什博奕(Bash Game) 

只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个。最后取光者得胜。  


显然,如果n=m+1,那么由于一次最多只能取m个,所以,无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后者取胜。因此我们发现了如何取胜的法则:如果n=(m+1)r+s,(r为任意自然数,s≤m),那么先取者要拿走s个物品,如果后取者拿走k(≤m)个,那么先取者再拿走m+1-k个,结果剩下(m+1)(r-1)个,以后保持这样的取法,那么先取者肯定获胜。总之,要保持给对手留下(m+1)的倍数,就能最后获胜。 一般方法: 


步骤1:将所有终结位置标记为必败点(P点); 


步骤2: 将所有一步操作能进入必败点(P点)的位置标记为必胜点(N点) 


步骤3:如果从某个点开始的所有一步操作都只能进入必胜点(N点) ,则将该点标记为必败点(P点) ; 


步骤4: 如果在步骤3未能找到新的必败(P点),则算法终止;否则,返回到步骤2

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>

using namespace std;

int main()
{
int n,m;
int i;
while(~scanf("%d%d",&m,&n))
{
if(m % (n+1) == 0)//无论第一个人怎么取,第二个人只要保证剩下的为n+1的倍数即可获胜
{
printf("none\n");
continue;
}
else
{
if(m <= n)//第一个人直接可以取完
{
printf("%d",m);
for(i=m+1; i<=n; i++)
{
printf(" %d",i);
}
printf("\n");
}
else//把上面介绍的s取走,这样就就能边被动为主动,让自己变为上面意义上的第二个人
{
printf("%d\n",m %(n+1));
}
}
}
return 0;
}



举报

相关推荐

0 条评论