bzoj4600: [Sdoi2016]硬币游戏

这么傻逼的博弈都做那么久真是日了

状态数极少,直接暴力算sg就完事了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int _=1e2;
const int maxn=3*1e4+_;
const int mbit=16+2;
int Log2[maxn],Log3[maxn];

int sg[mbit][mbit];
int tim,v[110000];
void yu(int n,int m,int K)
{
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
        {
            tim++;
            
            for(int p=1;p<=i;p++)
                for(int q=1;q<=K&&p*q<=i;q++)
                {
                    int s=0;
                    for(int k=1;k<=q;k++)s^=sg[i-p*k][j];
                    v[s]=tim;
                }
                
            for(int p=1;p<=j;p++)
                for(int q=1;q<=K&&p*q<=j;q++)
                {
                    int s=0;
                    for(int k=1;k<=q;k++)s^=sg[i][j-p*k];
                    v[s]=tim;
                }
                
            int tp=0;
            while(v[tp]==tim)tp++;
            sg[i][j]=tp;
        }
}

int get2(int x)
{
    int ret=0;
    while(x%2==0)ret++,x/=2;
    return ret;
}
int get3(int x)
{
    int ret=0;
    while(x%3==0)ret++,x/=3;
    return ret;
}
int main()
{
    Log2[1]=0,Log3[1]=0;
    Log2[2]=1,Log3[2]=0;
    for(int i=3;i<maxn;i++)
        Log2[i]=Log2[i/2]+1,Log3[i]=Log3[i/3]+1;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,op,ans=0;
        scanf("%d%d",&n,&m); yu(Log2[n],Log3[n],m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&op);
            if(op==0)ans^=sg[get2(i)][get3(i)];
        }
        puts(ans==0?"lose":"win");
    }
    
    return 0;
}

 

posted @ 2019-03-18 14:12  AKCqhzdy  阅读(118)  评论(0编辑  收藏  举报