博弈论个人的一点小总结

目录

一堆的 ,拿的石子某个范围内,在1~K之间

N堆的石子,每次只能从一堆中取

两堆,从一堆中取任意个或从2堆中取相同数量的石子,但不可不取 

SG函数


一堆的 ,拿的石子某个范围内,在1~K之间


 1066 Bash游戏  也加巴什博弈

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

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

例如N = 3,K = 2。无论A如何拿,B都可以拿到最后1颗石子。

Input

第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行2个数N,K。中间用空格分隔。(1 <= N,K <= 10^9)

Output

共T行,如果A获胜输出A,如果B获胜输出B。

Input示例

4
3 2
4 2
7 3
8 3

Output示例

B
A
A
B

 贴上代码:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
#define ll long long

int main()
{
	int n,k,t;
	scanf("%d",&t);
	while(t--)
    {
        scanf("%d%d",&n,&k);
        if(n%(k+1)==0)
            printf("B\n");
        else
            printf("A\n");
    }
	return 0;

}

N堆的石子,每次只能从一堆中取

1069 Nim游戏  也叫尼姆博弈

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

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

例如:3堆石子,每堆1颗。A拿1颗,B拿1颗,此时还剩1堆,所以A可以拿到最后1颗石子。

Input

第1行:一个数N,表示有N堆石子。(1 <= N <= 1000)
第2 - N + 1行:N堆石子的数量。(1 <= A[i] <= 10^9)

Output

如果A获胜输出A,如果B获胜输出B。

Input示例

3
1
1
1

Output示例

A

贴上代码:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
#define ll long long

int main()
{
	int n;
	while(scanf("%d",&n)==1)
    {
        int ans=0;
        for(int i=0;i<n;i++)
        {
            int x;
            scanf("%d",&x);
            ans^=x;
        }
        if(ans==0)
            printf("B\n");
        else 
            printf("A\n");
    }
	return 0;

}

两堆,从一堆中取任意个或从2堆中取相同数量的石子,但不可不取 

1072 威佐夫游戏

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

有2堆石子。A B两个人轮流拿,A先拿。每次可以从一堆中取任意个或从2堆中取相同数量的石子,但不可不取。拿到最后1颗石子的人获胜。假设A B都非常聪明,拿石子的过程中不会出现失误。给出2堆石子的数量,问最后谁能赢得比赛。

例如:2堆石子分别为3颗和5颗。那么不论A怎样拿,B都有对应的方法拿到最后1颗。

Input

第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行2个数分别是2堆石子的数量,中间用空格分隔。(1 <= N <= 2000000)

Output

共T行,如果A获胜输出A,如果B获胜输出B。

Input示例

3
3 5
3 4
1 9

Output示例

B
A
A

相关问题

Bash游戏

0

 Bash游戏 V2 

10

 Bash游戏 V3 

20

 Nim游戏

0

 Bash游戏 V4 

40

威佐夫游戏 

0

 威佐夫游戏 V2 

0


这种题之前学过,不过现在忘得差不多了
我们先来找找规律吧:

假定下面的判断如果为X表示A输,Y表示A赢

第一堆 第二堆 判断
       0       0      X
       0       1      Y
       1        1      Y
       1            2      X
       2       2      Y
       2        3      Y  
      3       3      Y
      3       4      Y
      3        5      X
     ...    ...      ...
      4        7       X
      ...      ...      ...
      6        10       X
      ...        ...      ...

 我们讨论A输的时候两堆石子的情况,我们从数量小的开始:(0,0)---->(1,2)---->(3,5)---->(4,7)---->(6,10)---->·········

                                                                 再看看两堆的差值:      0            1           2             3               4

我们发现,每个样例的第一个堆的数量都是前面没有出现的自然数,通过差值逐渐增加的规律得到两堆差值,进而得到另一堆的数量

这些样例也叫奇异局势,就是面对这种情况必输

然后我看了看以前学长讲的ppt,上面有个结论:

以上面的(6,10)为例,即A=6,B=10, 那么等式左边就等于6.472···,向下取整后就等于6,恰好等于A的值,也就是奇异局势

具体得来的其实我也不太清楚,估计还得问问数学家


贴上代码吧:

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
#define ll long long

int main()
{
	int n;
	int a,b;
	while(scanf("%d",&n)==1)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            int A=a>b?b:a;
            int B=a>b?a:b;
            if((int)((sqrt(5.0)+1)/2*(B-A))==A)
                printf("B\n");
            else
                printf("A\n");
        }
    }
	return 0;

}

最后再加上个SG函数

SG函数

其实下面讲的为甚sg那样求,然后判断Sg(x)^Sg(y)^Sg(z) == 0时就是奇异局势,我也不理解其中的缘由,先记着吧

SG函数可以看成各个Nim游戏的和,将问题分成各种Nim问题,从而简化了问题。

例如:有三堆石头,每次能取的数量为斐波拉系数,即只能取1,2,3,5,8,13,21……这些石头的数量。

首先

     定义mex运算:表示最小的不属于这个集合的数。例如:mex{0,1,2,3} = 4mex{0,1,3,4,5} = 2mex{} = 0

    对于任意的xSg(x) = mex{S}Sx的后继状态数值的集合,假设有三个状态Sg(a)Sg(b)Sg(c)。那么Sg(x) = mex{Sg(a)Sg(b)Sg(c)}

    设有三堆石头为xyz这三堆。那么只要判断Sg(x)^Sg(y)^Sg(z) == 0就行,当成立时就说明面对的是奇异局势,必输,反正必赢。

举例:

附上hdu 1848题目:

Fibonacci again and again

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11629    Accepted Submission(s): 5015


 

Problem Description

任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的:
F(1)=1;
F(2)=2;
F(n)=F(n-1)+F(n-2)(n>=3);
所以,1,2,3,5,8,13……就是菲波那契数列。
在HDOJ上有不少相关的题目,比如1005 Fibonacci again就是曾经的浙江省赛题。
今天,又一个关于Fibonacci的题目出现了,它是一个小游戏,定义如下:
1、  这是一个二人游戏;
2、  一共有3堆石子,数量分别是m, n, p个;
3、  两人轮流走;
4、  每走一步可以选择任意一堆石子,然后取走f个;
5、  f只能是菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量);
6、  最先取光所有石子的人为胜者;

假设双方都使用最优策略,请判断先手的人会赢还是后手的人会赢。

 

Input

输入数据包含多个测试用例,每个测试用例占一行,包含3个整数m,n,p(1<=m,n,p<=1000)。
m=n=p=0则表示输入结束。

 

Output

如果先手的人能赢,请输出“Fibo”,否则请输出“Nacci”,每个实例的输出占一行。

 

Sample Input

 

1 1 1 1 4 1 0 0 0

 

Sample Output

 

Fibo Nacci

 

Author

lcy

 

Source

ACM Short Term Exam_2007/12/13

 

Recommend

lcy


具体实现请看代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
int sg[1001];
int fa[1001];
int mex[1010];
void getsg(int n)
{


    for(int i=1;i<=n;i++)
    {
        memset(mex,0,sizeof(mex));

        for(int j=0;fa[j]<=i;j++)
        {
            mex[sg[i-fa[j]]]=1;
        }
        for(int k=0;;k++)
        {
            if(!mex[k])
            {
                sg[i]=k;
                break;
            }
        }
    }
}
int a[120];
int main()
{
    int t;
    int x,y,z;
    int flag;
    fa[0]=1;
    fa[1]=2;
    for(int i=2;i<=1000;i++)
        fa[i]=fa[i-1]+fa[i-2];
   getsg(1010);
    while(scanf("%d%d%d",&x,&y,&z)!=EOF&&(x||y||z))
    {
        if(sg[x]^sg[y]^sg[z]) printf("Fibo\n");
        else printf("Nacci\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42373330/article/details/82056140