• 【LOJ】#2067. 「SDOI2016」硬币游戏


    题解

    c一样的就是一个独立的游戏

    我们对于2和3的指数
    sg[i][j] 表示(c cdot 2^i cdot 3^j)的棋子,只有这个硬币是反面,翻转的硬币是正面的sg值

    枚举sg函数所有可能的局面,每个后继局面的sg值,就是所有被翻到背面的硬币sg值的异或和

    我们忽略了反转当前硬币前面可能不是全部正面,但是这是正确的,我们可以证明一下

    如果一个局面所有背面朝上的棋子sg函数异或起来为(x)
    (x!=0)
    那么我们找到(x)最高位是(2^k),我们找到一个含有(2^k)的硬币(a_n)(x^a_n < a_n) 我们选择这个棋子的后继局面中等于(x^a_n)的那个即可将局面的sg异或值变成0

    (x = 0)
    如果一个局面行动后的后继局面中有0,那么这个局面的值一定不为0
    所有可操作的局面sg的值都不为0,且后继局面中的值与该局面sg值不等
    故而无论如何操作,sg值为正

    代码

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define MAXN 1000005
    #define mo 999999137
    #define pb push_back
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') {
            res = res * 10 + c - '0';
            c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    int sg[55][55];
    bool f[60005];
    int N,MAXQ,a[30005];
    void Init() {
        memset(sg,0,sizeof(sg));
        sg[0][0] = 0;
        for(int i = 0 ; i <= 50 ; ++i) {
            for(int j = 0 ; j <= 50 ; ++j) {
                if(i == 0 && j == 0) continue;
                memset(f,0,sizeof(f));
                if(i != 0) {
                    for(int p = 1 ; p <= i ; ++p) {
                        int t = 0;
                        for(int q = 1 ; q <= min(MAXQ,i / p) ; ++q) {
                            t ^= sg[i - p * q][j];
                            f[t] = 1;
                        }
                    }
                }
                if(j != 0) {
                    for(int p = 1 ; p <= j ; ++p) {
                        int t = 0;
                        for(int q = 1 ; q <= min(MAXQ,j / p) ; ++q) {
                            t ^= sg[i][j - p * q];
                            f[t] = 1;
                        }
                    }
                }
                int p = 0;
                while(f[p]) ++p;
                sg[i][j] = p;
            }
        }
    }
    void Solve() {
        read(N);read(MAXQ);
        Init();
        int ans = 0;
        for(int i = 1 ; i <= N ; ++i) {
            read(a[i]);
            if(!a[i]) {
                int t = i,c2 = 0,c3 = 0;
                while(t % 2 == 0) t /= 2,++c2;
                while(t % 3 == 0) t /= 3,++c3;
                ans ^= sg[c2][c3];
            }
        }
        if(!ans) puts("lose");
        else puts("win");
    }
    int main() {
        int T;
        read(T);
        while(T--) {
            Solve();
        }
        return 0;
    }
    
  • 相关阅读:
    iOS 记录近期遇到的几个bug
    iOS转场动画封装
    iOS 页面滑动与标题切换颜色渐变的联动效果
    Realm数据持久化方案的简单介绍和使用(二)
    某互联网科技公司的一道逻辑面试题
    js获取本月,本季度,上个季度,本周,上周的起始和结束时间
    CSS样式说明
    a标签的样式
    CSS3的> 和@
    CSS中的position定位
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9523454.html
Copyright © 2020-2023  润新知