zoukankan      html  css  js  c++  java
  • Bzoj4600--Sdoi2016硬币游戏

    题意 :

    Description

    Alice和Bob现在在玩的游戏,主角是依次编号为1到n的n枚硬币。每一枚硬币都有两面,我们分别称之为正面和反
    面。一开始的时候,有些硬币是正面向上的,有些是反面朝上的。Alice和Bob将轮流对这些硬币进行翻转操作,且
    Alice总是先手。具体来说每次玩家可以选择一枚编号为x,要求这枚硬币此刻是反面朝上的。对于编号x来说,我
    们总可以将x写成x=c*2^a*3^b,其中a和b是非负整数,c是与2,3都互质的非负整数,然后有两种选择第一种,选择
    整数p,q满足a>=p*q,p>=1且1<=q<=MAXQ,然后同时翻转所有编号为c*2^(a-p*j)*3^b的硬币,其中j=0,1,2,..,q。第
    二种,选择整数p,q满足b>=p*q,p>=1且1<=q<=MAXQ,然后同时翻转所有编号为c*2^a*3^(b-p*j)的硬币,其中j=0,1,
    2,..,q。可以发现这个游戏不能不先进行下去,当某位玩家无法继续操作上述操作时,便输掉了游戏。作为先手的
    Alice,总是希望可以在比赛开始之前就知道自己能否获胜。她知道自己和Bob都是充分聪明的,所以在游戏过程中
    两人都会最优化自己的策略并尽量保证自己处于不败的情形中

    Input

    本题有多组测试数据,第一行输入一个整数T,表示总的数据组数。之后给出T组数据
    每组数据第一行输入两个整数n,MAXQ
    第二行输入n个整数,第i个数表示第i个硬币的初始状态,0表示反面朝上,1表示正面朝上
    对于100%的数据1<=n<=30000,1<=MAXQ<=20,t<=100。

    Output

    输出共有t行。对于每一组数据来说,如果Alice先手必胜,则输出"win"(不包括引号),否则输出"lose"
     
    ------------------------------------------------此后一千里---------------------------------------------
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    考虑每一个编号为x的硬币翻动的sg值,那么这个sg值显然只与x中2,3的因子个数相关,因为c不同的硬币互相之间不影响。
    那么我们设定sg[i][j]为x=c*2^i*3^j的硬币翻动的sg值,那么转移可以去暴力枚举后继局面,即我们去枚举去2的因子,和去3的因子,那么能够达到的后继局面sg值就是所有枚举到的后继状态的异或和。
    然后对于给出局面就可以直接计算sg值了。
    又涨了新的博弈姿势,发现博弈姿势永远涨不完。。。
    ps :调了半天错发现自己一直以为1是能翻的,0是不能翻的。。。。
    代码 :
    /*
    Lelouch vi Britannia here commands you , all of you , die !
    */
    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define low(x) ((x)&(-(x)))
    #define LL long long
    #define eps 1e-9
    using namespace std;
    
    #define int int
    inline int Max(int a,int b) {return a>b?a:b;}
    inline int Min(int a,int b) {return a<b?a:b;}
    inline int Abs(int a) {return a>0?a:-a;}
    inline int Sqr(int a) {return a*a;}
    #undef int
    
    int sg[22][22][22];
    bool go[100];int two[30005],three[30005];
    
    void Pre(int n) {
        int mxq,i,j,p,q,s,k;
        for(mxq=1;mxq<=20;mxq++) {
            for(i=0;i<=20;i++) 
                for(j=0;j<=20;j++) {
                    for(p=1;p<=i;p++) 
                        for(q=1;q<=mxq&&p*q<=i;q++) {
                            for(s=-1,k=1;k<=q;k++) 
                                s=s==-1?sg[mxq][i-p*k][j]:s^sg[mxq][i-p*k][j];
                            if(~s) go[s]=1;
                        }
                    for(p=1;p<=j;p++) 
                        for(q=1;q<=mxq&&p*q<=j;q++) {
                            for(s=-1,k=1;k<=q;k++) 
                                s=s==-1?sg[mxq][i][j-p*k]:s^sg[mxq][i][j-p*k];
                            if(~s) go[s]=1;
                        }
                    for(s=0;true;s++) 
                        if(!go[s]) {
                            sg[mxq][i][j]=s;break;
                        }
                    memset(go,0,sizeof(go));
                }
        }
        for(int i=1;i<=n;i++) {
            two[i]=i%2?0:two[i/2]+1;
            three[i]=i%3?0:three[i/3]+1;
        }
    }
    
    int T,n,maxq,ans;
    
    int main() {
        scanf("%d",&T);
        Pre(30000);
        while(T--) {
            ans=0;
            scanf("%d%d",&n,&maxq);
            for(int a,i=1;i<=n;i++) {
                scanf("%d",&a);
                if(!a) ans^=sg[maxq][two[i]][three[i]];
            }
            ans!=0?puts("win"):puts("lose");
        }
        return 0;
    }
    /*
    Hmhmhmhm . Yes , I am killer.
    */
    View Code
  • 相关阅读:
    HDU2059(龟兔赛跑)
    pat 1012 The Best Rank
    pat 1010 Radix
    pat 1007 Maximum Subsequence Sum
    pat 1005 Sign In and Sign Out
    pat 1005 Spell It Right
    pat 1004 Counting Leaves
    1003 Emergency
    第7章 输入/输出系统
    第六章 总线
  • 原文地址:https://www.cnblogs.com/ihopenot/p/6581944.html
Copyright © 2011-2022 走看看