题目背景
(原创)
有一天 pb和zs玩游戏 你需要帮zs求出每局的胜败情况
题目描述
游戏规则是这样的: 每次一个人可以对给出的数进行分割,将其割成两个非零自然数,之后由另一个人选择留下两个数中的其中一个;之后由另一个人进行分割这个剩下的数,重复步骤……
当一个人无法对数进行分割的时候游戏结束,另一个人获胜
现在要你求出N次游戏的胜败
每局由pb先进行分割,如果pb赢输出"pb wins" 如果zs赢输出"zs wins"
注:双方都是绝顶聪明的
输入格式
第一行一个数N,表示数据组数
之后N行,每行一个数M,表示每局初始的数
输出格式
共N行,每行一串字符 表示游戏结果
输入输出样例
输入
5
1
3
7
20
5
输出
zs wins
zs wins
zs wins
pb wins
zs wins
说明/提示
1<N<50 1<=m<=1000000000
*************************************************************************************************************************************************************************************************************************************
解题思路:
这是一道很简单的博弈问题,甚至只要多写几组数据测试一下就可以找到规律,就是偶数的时候先手必胜,奇数的时候后手必胜,下面我们来分析一下这是为什么
博弈问题还是自底向上的寻找解决思路,我们来简单的模拟一下,
n=1,先手无法再分,先手必败
n=2,先手将其分为1+1,后手无法再分,先手必胜
n=3,先手只能分为1+2,后手遇见n=2情况,后手必胜
n=4,先手将其分为1+4,后手遇见n=3的情况,这个时候则变成了先手必胜
……
我们首先知道,任何一个奇数只能转化成一个奇数加一个偶数,也就是说如如果先手是奇数,先手一定会拆出一个偶数m,后手就可以把m转化为1+(m-1),(m-1)就是奇数,让先手始终面对奇数的情况,这样最后先手一定会遇见3拆出一个1+2的状态,这时候后手就是赢了,也就是说如果n是奇数,先手就是必败的,反之如果先手是n偶数,那么拆成1+(n-1),让后手始终面对奇数,这样先手就是必胜的。
另外对于博弈论偶然发现了一句话觉得对于理解必胜态,必败态,最优策略有很大的帮助,分享给大家
必败态从来没有最佳策略, 博弈也不是双方的博弈, 而是处在必胜态的那方和自己博弈. 而这场博弈, 由于绝顶聪明的前提, 是必胜的, 而我们要做的, 只是找出谁有跟自己博弈的机会.
下面附上ac代码
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
#define M 1000000
int num[15]={2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
ll t,n,m,p;
cin>>t;
while(t--)
{
ll n;
ll cntpb=0,cntzs=0,step=1;
cin>>n;
if(n%2==0)
cout<<"pb wins"<<endl;
else
cout<<"zs wins"<<endl;
}
return 0;
}