bzoj 4600 硬币游戏 Posted on 2019-06-04 | Views: 博弈论. 操作一枚硬币,它只能影响到 $c$ 与自己相同的硬币.于是 $SG$ 函数就只需要 $a,b$ 两个状态. 而 $a,b$ 是指数,非常小,所以状态数目也很少,直接暴力计算 $SG$ 函数即可. 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=25;int SG[MAXN][MAXN][MAXN];void init_SG(int maxq){ vector<int> s; int tmp=0; for(int a=0;a<=20;++a) for(int b=0;b<=20;++b) { s.clear(); for(int p=1;p<=20;++p,tmp=0) for(int q=1;q<=maxq && p*q<=a;++q) { tmp^=SG[maxq][a-p*q][b]; s.push_back(tmp); } for(int p=1;p<=20;++p,tmp=0) for(int q=1;q<=maxq && p*q<=b;++q) { tmp^=SG[maxq][a][b-p*q]; s.push_back(tmp); } sort(s.begin(),s.end()); int siz=s.size(); if(!siz || s[0]) { SG[maxq][a][b]=0; continue; } for(int i=1;i<siz;++i) { if(s[i]-s[i-1]>=2) { SG[maxq][a][b]=s[i-1]+1; break; } } if(!SG[maxq][a][b]) SG[maxq][a][b]=s[siz-1]+1; }}int n,maxq;int main(){ for(int i=1;i<=20;++i) init_SG(i); int T=read(); while(T--) { n=read(),maxq=read(); int ans=0; for(int i=1;i<=n;++i) { int dir=read(); if(dir) continue; int x=i,a=0,b=0; while(x%2==0) ++a,x/=2; while(x%3==0) ++b,x/=3; ans^=SG[maxq][a][b]; } if(ans) puts("win"); else puts("lose"); } return 0;}