B. GameGame(博弈,思维)

感觉还是很考验思维的…

部分思路来自茄子大大!!

记 录 一 下 有 多 少 数 包 含 第 x 位 二 进 制 , 记 作 t w o [ x ] 记录一下有多少数包含第x位二进制,记作two[x] xtwo[x]

若 t w o [ x ] 为 偶 数 , 那 么 不 管 怎 么 选 , 要 么 两 个 数 最 后 这 位 都 是 偶 数 , 要 么 都 是 奇 数 , 不 用 管 若two[x]为偶数,那么不管怎么选,要么两个数最后这位都是偶数,要么都是奇数,不用管 two[x],,,,

所 以 找 到 最 高 位 的 n u m 使 得 t w o [ n u m ] % 2 = = 1 所以找到最高位的num使得two[num]\%2==1 num使two[num]%2==1

最后选的数一定是在这一位分出胜负

那 么 现 在 的 情 况 就 是 , 谁 能 保 证 这 一 位 拿 到 奇 数 个 1 , 谁 就 赢 那么现在的情况就是,谁能保证这一位拿到奇数个1,谁就赢 ,1,


Ⅰ . 当 ( t w o [ n u m ] − 1 ) / 2 是 偶 数 Ⅰ.当(two[num]-1)/2是偶数 .(two[num]1)/2

先 手 必 胜 , 因 为 先 手 可 以 先 拿 一 个 1 先手必胜,因为先手可以先拿一个1 ,1

然 后 剩 下 ( t w o [ n u m ] − 1 ) / 2 次 等 后 手 拿 了 1 , 我 再 去 拿 1 然后剩下(two[num]-1)/2次等后手拿了1,我再去拿1 (two[num]1)/21,1

这 样 由 于 ( t w o [ n u m ] − 1 ) / 2 是 偶 数 , 所 以 先 手 拿 到 奇 数 个 1 , 必 胜 这样由于(two[num]-1)/2是偶数,所以先手拿到奇数个1,必胜 (two[num]1)/2,1,


Ⅱ . 当 ( t w o [ n u m ] − 1 ) / 2 是 奇 数 Ⅱ.当(two[num]-1)/2是奇数 .(two[num]1)/2

若 n 也 是 奇 数 , 那 么 现 在 有 奇 数 个 位 置 ( t w o [ n u m ] ) 含 1 , 偶 数 个 位 置 不 含 1 \color{Red}若n也是奇数,那么现在有奇数个位置(two[num])含1,偶数个位置不含1 n,(two[num])1,1

那 么 后 手 一 直 跟 着 先 手 选 , 先 手 拿 1 后 手 才 去 拿 1 那么后手一直跟着先手选,先手拿1后手才去拿1 ,11

先 手 拿 ( t w o [ n u m ] − 1 ) / 2 次 1 , 后 手 拿 ( t w o [ n u m ] − 1 ) / 2 + 1 个 1 先手拿(two[num]-1)/2次1,后手拿(two[num]-1)/2+1个1 (two[num]1)/21,(two[num]1)/2+11

后 手 必 胜 。 后手必胜。

注 意 到 这 里 没 有 考 虑 偶 数 个 不 含 1 的 位 置 , 因 为 只 有 当 先 手 选 不 含 1 的 位 置 后 手 才 选 。 又 因 为 是 偶 数 个 位 置 不 含 1 , 所 以 相 当 于 没 有 影 响 注意到这里没有考虑偶数个不含1的位置,因为只有当先手选不含1的位置后手才选。又因为是偶数个位置不含1,所以相当于没有影响 1,11,

若 n 是 偶 数 呢 ? \color{Red}若n是偶数呢? n?

那 么 现 在 有 奇 数 个 位 置 ( t w o [ n u m ] ) 含 1 , 奇 数 个 位 置 不 含 1 那么现在有奇数个位置(two[num])含1,奇数个位置不含1 (two[num])1,1

现 在 不 含 1 的 位 置 有 奇 数 个 了 , 不 能 像 前 面 一 样 不 管 了 现在不含1的位置有奇数个了,不能像前面一样不管了 1,

但 是 先 手 可 以 先 拿 掉 一 个 不 含 1 的 位 置 但是先手可以先拿掉一个不含1的位置 1

现 在 变 成 有 奇 数 个 位 置 ( t w o [ n u m ] ) 含 1 , 偶 数 个 位 置 不 含 1 现在变成有奇数个位置(two[num])含1,偶数个位置不含1 (two[num])1,1

后n是奇数的情况一样了,只不过现在的先手相当于前面的后手,所以先手必胜

/*找到最大的id,使得有奇数个数包含这一位 */
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],two[32],t,n;
int main()
{
	cin >> t;
	while( t-- )
	{
		memset(two,0,sizeof(two));
		cin >> n;
		for(int i=1;i<=n;i++)
		{
			cin >> a[i];
			for(int j=0;j<=30;j++)
			if( (1<<j)&a[i] )	two[j]++;
		}
		int num=-1;
		for(int i=0;i<=30;i++)//找最高位的奇数1
			if( two[i]%2==1 )	num=i;
		if( num==-1 )	cout << "DRAW\n" ;
		else
		{
			if( (two[num]-1)/2%2==0 )	cout << "WIN\n" ;
			else if( (two[num]-1)/2%2==1&&n%2==1 ) 	cout << "LOSE\n" ;
			else	cout << "WIN\n" ;
		} 
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值