• 洛谷 [P2594] 染色游戏


    博弈论+SG函数的应用

    这是一个二维翻硬币问题

    一维翻硬币问题有一个结论:

    局面的SG值等于局面中所有反面朝上的硬币单独存在时的SG值的异或和

    这个结论同样适用于二维的翻硬币问题

    证明可以用数学归纳法,这里省去(其实是我不会证)

    那么如何求每个硬币单独反面朝上时的SG值,首先考虑递推

    然而不会推

    那就只好打表找规律

    有如下规律:

    [SG(i, j) = egin {cases} lowbit(i + j - 1), quad i == 1 || j == 1\ 2 ^{ i + j - 2}, quad i != 1 &&j != 1 end{cases} ]

    我们发现SG函数值最大可达 2 的 200 次方,无法用long long 储存

    我们可以用 bool 数组 或 bitset 来模拟

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int T, sg[105][105], n, m, a[10005], cnt, mp[1200];
    bool f[300];
    int lowbit(int x) {
    	return x & (-x);
    }
    int getsg(int a, int b){
    	if(a == 1 || b == 1){
    		return mp[lowbit(a + b - 1)];
    	}else return a + b - 2;
    }
    int main() {
    	for(int i = 0 ; i <=9 ; i++) {
    		mp[(1<<i)] = i;
    	}
    	cin>>T;
    	while(T--) {
    		memset(f, 0, sizeof(f));
    		cin>>n>>m;
    		int ans = 0;
    		for(int i = 1 ; i <= n ; i++) {
    			for(int j = 1 ; j <= m ; j++) {
    				char c ;
    				scanf(" %c ", &c);
    				if(c !='H'){
    					f[getsg(i, j)] ^= 1;
    				}
    			}
    		}
    		for(int i = m + n - 1 ; i >= 0 ; i--) if(f[i]) {ans = 1;break;}
    		if(ans) printf("-_-
    ");
    		else printf("=_=
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    IO复习
    递归
    转换流
    编码与解码
    打印流(printStream)
    Properties
    【转】将Visual Studio武装到底
    【转】VS2008中的自定义格式化代码
    C++开发工具的常用插件
    抽烟的注意事项
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8509330.html
Copyright © 2020-2023  润新知