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

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1066

必胜策略:令 n = (k + 1) * r + s ; A第一次取s个,让B面对k+1倍数的局面,如果B取m个则A取k+1 - m个。

#include <cstdio>
#include <cstring>
using namespace std;

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

	return 0;
}

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

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1067

分析:连续找一些书测试,可以发现当 n % 7 == 0 || == 2 时B胜,其余情况A胜

#include <cstdio>
using namespace std;

int main()
{
	int t, n;
	scanf("%d", &t);
	while( t-- )
	{
		scanf("%d", &n);
		int tmp = n % 7;
		if( tmp == 0 || tmp == 2 )
			printf("B\n");
		else
			printf("A\n");
	}

	return 0;
}

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

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

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1069

分析:尼姆博弈,对于一个Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当a1^a2^...^an=0,其中^表示异或(xor)运算.

#include <cstdio>
using namespace std;

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

	return 0;
}

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

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

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1072

分析:威佐夫博弈

两个人如果都采用正确操作,那么面对非奇异局势,先拿者必胜;反之,则后拿者取胜. 局势(N,M)(N<M)满足

N==(int)((1.0+sqrt(5.0))/2.0*(M-N))时,该局势为奇异局势,后拿者必胜.

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

int main()
{
	int t;
	scanf("%d", &t);
	while( t-- )
	{
		int a, b;    // n m
		scanf("%d%d", &a, &b);
		if( a > b )
			swap(a, b);
		int tmp = (int) ((1.0 + sqrt(5.0)) / 2.0 * (b - a));	// 奇异局势
		if( a == tmp )
			printf("B\n");
		else
			printf("A\n");
	}

	return 0;
}