nimk博弈的一道水题--SDNU OJ 1253

Description

Alice have a friend Bob, they like play games very much, They like to play games is to grab the stone, this classic game they play much times, so today they intend to make the classic reproduction, playing an overnight grab stone,  they are two people who like innovation, so this time they got a new game is played

a. There are N heap stones here.

b. Each time you can select stones that do not exceed M heap for any operation

c.   They play game in turns and cannot do nothing

d.   People who cannot move stones are losers

e.   Alice first

Input

The first line is T(0 < T <= 1000) T is TestCase

Next line is N, M(0 < N, M <= 10000)

Next line follow N number P, P is the number of stones in the stone heap(0 < P <= 10000)

Output

Case #TestCase: winner

If Alice win output Alice, otherwise Bob

Sample Input

1
5 1
1 2 3 4 5

Sample Output

Case #1: Alice

知道了nimk博弈这个家伙之后,这题要有多水有多水,比赛是还想着什么巴什博弈+nim等操作,-_-||

欲学nimk博弈,必先了解一下nim博弈,nimk与nim最大的区别就在于nim是在是取一堆进行操作,而nimk是取k堆进行操作(怪不得+了个k)

所以和nim博弈时的异或后模2不同,这里是要模k+1的!!(取1堆时模2,取k堆时就模k+1喽)

我知道你们最想看的东西在这里:

const int MAXN = 10005;
int SG[MAXN];//需要处理的SG值数组
int XOR[MAXN];//储存每一个二进制位上的和
int xxx;//储存每一个SG值的临时变量
int num;//储存当前SG值有多少位的临时变量
int maxn;//储存最大的SG值位数

bool solve(int N,int M)//N表示SG数组的大小,从1到N,M表示每次可以取1到M堆
{
	memset(XOR, 0, sizeof XOR);
	maxn = -1;
	for (int i = 1; i <= N; i++)
	{
    	xxx = SG[i];
		num = 0;
		while (xxx)
		{
			XOR[num] += xxx&1;
			num++;
			xxx >>= 1;
		}
		maxn = max(maxn, num);
	}
	for (int i = 0; i < maxn; i++)
		if (XOR[i] % (M + 1))
			return true;//返回true表示先手必胜
	return false;//返回false表示先手必败
}

wtf ?,上面的你们都懒得看,代码给你们

//nimk博弈问题 
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

const int maxn = 10005;
int sg[maxn], eor[maxn];
int num, maxs, hy;

int max(int x, int y)
{
	if(x >= y)
		return x;
	else
		return y;
}
bool nimk(int n, int m)
{
	memset(eor, 0, sizeof(eor));
	maxs = -1;
	for(int i = 1; i <= n; i++){
		hy = sg[i];
		num = 0;
		while(hy){
			eor[num] += hy&1;
			num++;
			hy >>= 1; 
		}
		maxs = max(maxs, num);
	}
	for(int i = 0; i < maxs; i++){
		if(eor[i] % (m+1))
			return true;
	}
	return false;
}
int main()
{
	int T;
	cin >> T;
	int cas = 1;
	while(T--){
		memset(sg, 0, sizeof(sg));
		int n, m;
		cin >> n >> m;
		for(int i = 1; i <= n; i++){
			cin >> sg[i];
		}	
		if(nimk(n, m)){
			printf("Case #%d: Alice\n", cas);
		}
		else
			printf("Case #%d: Bob\n", cas);
		cas++;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值