這道題目比較神仙。
首先觀察結束狀態,即\(P\)狀態,此時一定是全部的豆子都在最後一個瓶子中。
發現每次的轉移必定是拿出一棵豆子,放兩顆豆子,因此一個瓶子中不管豆子數量是多少,咱們均可以把全部的豆子拆開當作單個的\(Nim\)遊戲(由於早晚都要所有進入到\(n\)號瓶子的)
發現若是有兩個在同位置的豆子,勝負結果是不會改變的,由於後手能夠一直模仿先手的動做進行單個遊戲。所以全部位置的豆子等價於這個位置的豆子總數對於\(2\)的餘數。
那麼,如今問題變成了,給你一棵豆子,他在\(i\)位置,回答勝負狀況。
那麼預處理\(SG\)函數便可。這個\(SG\)函數從後往前求。ios
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define MAX 50 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } int n,a[MAX],SG[MAX]; bool vis[MAX]; int main() { int T=read(); while(T--) { n=read();memset(SG,0,sizeof(SG)); for(int i=1;i<=n;++i)a[i]=read(); for(int i=n-1;i;--i) { memset(vis,0,sizeof(vis)); for(int j=i+1;j<=n;++j) for(int k=j;k<=n;++k) vis[SG[j]^SG[k]]=true; for(int j=0;;++j)if(!vis[j]){SG[i]=j;break;} } int cnt=0,A=0,B=0,C=0,sg=0; for(int i=1;i<=n;++i)if(a[i]&1)sg^=SG[i]; for(int i=1;i<=n;++i) if(a[i]) for(int j=i+1;j<=n;++j) for(int k=j;k<=n;++k) if(!(sg^SG[i]^SG[j]^SG[k])) { if(!cnt)A=i,B=j,C=k; ++cnt; } printf("%d %d %d\n%d\n",A-1,B-1,C-1,cnt); } return 0; }