• 【BZOJ 4600】【SDOI 2016】硬币游戏


    http://www.lydsy.com/JudgeOnline/problem.php?id=4600
    转化成nim游戏
    因为对于每一个反面朝上的硬币编号可以拆成(2^a3^bc),选择这个硬币可以翻的其他硬币的编号必须是c的倍数。
    那么如果两个单一游戏的c不同的话,只要a和b相同,那么状态的sg值也相同,所以存sg函数的状态时不用考虑c,只用考虑a和b即可。
    暴力枚举子状态进行转移。
    小神说这是博弈里比较水的一道题QwQ

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int in() {
    	int k = 0; char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar());
    	for(; c >= '0' && c <= '9'; c = getchar())
    		k = k * 10 + c - 48;
    	return k;
    }
    
    vector <int> a;
    int sg[23][23][23], n, maxq;
    
    void init(int SG[23][23]) {
    	int p, q, t = 0, tmp, num;
    	for(int i = 0; i <= 20; ++i)
    		for(int j = 0; j <= 20; ++j) {
    			a.clear();
    			for(p = 1; p <= i; ++p, t = 0)
    				for(q = 1; q <= maxq && p * q <= i; ++q) {
    					t ^= SG[i - p * q][j];
    					a.push_back(t);
    				}
    			for(p = 1; p <= j; ++p, t = 0)
    				for(q = 1; q <= maxq && p * q <= j; ++q) {
    					t ^= SG[i][j - p * q];
    					a.push_back(t);
    				}
    			
    			stable_sort(a.begin(), a.end());
    			if (!a.size() || a[0] != 0) continue;
    			tmp = num = 1;
    			while (tmp < a.size() && a[tmp] == a[tmp - 1]) ++tmp;
    			while (tmp < a.size()) {
    				if (a[tmp] != num) {
    					SG[i][j] = num;
    					break;
    				}
    				++tmp;
    				while (tmp < a.size() && a[tmp] == a[tmp - 1])
    					++tmp;
    				++num;
    			}
    			if (tmp == a.size()) SG[i][j] = num;
    		}
    }
    
    int T, m, pw2, pw3, ans;
    
    int main() {
    	for(maxq = 1; maxq <= 20; ++maxq)
    		init(sg[maxq]);
    
    	T = in();
    	while (T--) {
    		n = in(); maxq = in(); ans = 0;
    		for(int i = 1; i <= n; ++i) {
    			if (in()) continue;
    			pw2 = pw3 = 0;
    			m = i;
    			while (m % 2 == 0) ++pw2, m /= 2;
    			while (m % 3 == 0) ++pw3, m /= 3;
    			ans ^= sg[maxq][pw2][pw3];
    		}
    		puts(ans ? "win" : "lose");
    	}
    		
    	return 0;
    }
    
  • 相关阅读:
    Python-文件阅读(open函数)
    列表推导式练习
    Python-集合(set)
    Python-元组(tuple)
    Python-函数-聚合和打散
    Python-列表-非count的计数方法
    Python-字典(dict)
    Python-列表(list)
    Python-字符串
    求三个元素的最大值,和最小值。
  • 原文地址:https://www.cnblogs.com/abclzr/p/5947144.html
Copyright © 2020-2023  润新知