51nod-1714 B君的游戏

原题链接

基准时间限制:1 秒 空间限制:131072 KB 分值:40难度:4级算法题

B君和L君要玩一个游戏。刚开始有n个正整数   a i     。

双方轮流操作。每次操作,选一个正整数x,将其移除,再添加7个数字   x 1 ,x 2 ...x 7     。要求对于   x i     ,满足   0<=x i <x    且   x&x i =x i    

注意0不能被选取,所以这个游戏一定会结束,而谁无法操作谁就失败。
B君根据自己的经验,认为先手胜率高一点,所以B君是先手。
B君想知道自己是否必胜。
Input
第一行一个整数n (1 <= n <= 100000)
以下n行n个数ai (0 <= a_i < 2^64)
Output
如果先手必胜,输出"B",否则输出"L"。
Input示例
4
1
2
3
4
Output示例
B

注意到每个数的SG值,只和其中有多少个1有关。SG[i]是数x包含i个1的时候的SG值。然后,直接异或起来所有SG值即可。

用了158.1s算出所有sg值

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cstring>
#define maxn 70000000
using namespace std;
typedef long long LL;

int sg[65], maxs;
int cnt[maxn];
void dfs(int j, int m, int ans, int v){
	
	if(m == 0){
	    maxs = ans > maxs ? ans : maxs;
		cnt[ans] = 1;
		return ;
	}
	for(int i = v; i < j; i++){
		dfs(j, m-1, ans^sg[i], i);
	}
}
void Init(){
	
	sg[0] = 0;
	for(int i = 1; i <= 64; i++){
		for(int h = 0; h <= maxs; h++)
		  cnt[h] = 0;
		maxs = 0;
		dfs(i, 7, 0, 0);
		for(int j = 0; j < maxn; j++){
			if(cnt[j] == 0){
				sg[i] = j;
				break;
			}
		}	
	   printf("%d\n", sg[i]);
	}	
}
int main(){
	
	Init();
}

对输入的数算出其包含几个1,然后用sg值异或

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
typedef unsigned long long ull;

int sg[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 255, 256, 512, 
            1024, 2048, 3855, 4096, 8192, 13107, 16384, 21845, 
			27306, 32768, 38506, 65536, 71576, 92115, 101470, 
			131072, 138406, 172589, 240014, 262144, 272069, 
			380556, 524288, 536169, 679601, 847140, 1048576, 
			1072054, 1258879, 1397519, 2005450, 2097152, 2121415, 
			2496892, 2738813, 3993667, 4194304, 4241896, 4617503, 
			5821704, 7559873, 8388608, 8439273, 8861366, 11119275, 
			11973252, 13280789, 16777216, 16844349, 17102035, 
			19984054, 21979742, 23734709};
int main(){
	
//	freopen("in.txt", "r", stdin);
	int n;
	
	while(scanf("%d", &n) == 1){
		
		ull ans = 0, a;
		for(int i = 0; i < n; i++){
			scanf("%Iu64d\n", &a);
			int h = 0;
			ull d = 1;
			for(int i = 0; i <= 63; i++){
				if((d<<i)&a)
				 h++;
			}
			ans ^= sg[h];
		}
		if(ans == 0)
		 puts("L");
		else
		 puts("B");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值