CF919F A Game With Numbers
阿新 • • 發佈:2020-09-18
能轉移到必敗態的狀態就是必勝態,只能轉移到必勝態的狀態就是必敗態。
首先我們可以把狀態壓縮,發現狀態最多隻有 495 種。
然後如果一方是全 0 ,那麼這個狀態對應的答案就可以很容易得出
然後反著思考,從上面說的這些已知狀態逆向搜尋
DFS(m1,m2,k) 表示 A 是 m1 狀態,B 是 m2 狀態,k=0/1 表示當前是 A/B 操作的回合
每一個 m1,m2,k 只需要被搜尋一次,所以可以用一個 vis 陣列記憶一下有沒有搜過
注意,我們是從結果推到初始狀態,所以這裡的轉移也是倒過來轉移
如果當前狀態是必敗態,那麼轉移到下一個狀態(其實是上一個)就一定是必勝態,因為 能轉移到必敗態的狀態就是必勝態
如果當前狀態是必勝態,那麼就把能轉移到的狀態的計數器自增,如果某個狀態的計數器到達了能轉移到他的狀態的個數,那麼那個狀態就成為了必敗態,因為 只能轉移到必勝態的狀態就是必敗態
如果當前狀態不是必勝也不是必敗,那就別轉移給其他狀態,因為不確定
到最後還是不確定的起始狀態那就是 Deal
然後把所有狀態都預處理好,查詢直接輸出即可
至於記搜的複雜度... \(\mathcal O(\text{能過})\)
\(\texttt{Code}\)
// This code wrote by chtholly_micromaker(MicroMaker) #include <bits/stdc++.h> #define reg register #define mem(x,y) memset(x,y,sizeof x) #define ln puts("") using namespace std; template <class t> inline void read(t &s){s=0; reg int f=1;reg char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c))s=(s<<3)+(s<<1)+(c^48),c=getchar();s*=f;return;} template<class t,class ...A> inline void read(t &x,A &...a){read(x);read(a...);} template <class t> inline void write(t x){if(x<0)putchar('-'),x=-x; int buf[21],top=0;while(x)buf[++top]=x%10,x/=10;if(!top)buf[++top]=0; while(top)putchar(buf[top--]^'0');return;} int idx[9][9][9][9],idxcnt; int rev[500][5]; bool win[500][500][2],vis[500][500][2]; int cnt[500][500][2],Sum[500]; inline void dfs(int m[2],int k) { for(int i=0;i<=4;++i) for(int j=1;j<=4;++j) if(rev[m[k^1]][i]&&rev[m[k]][j]) { reg int c=(i-j+5)%5; if(!c) continue; reg int t[5];memcpy(t,rev[m[k^1]],sizeof t); --t[i],++t[c]; reg int nxtm[2];nxtm[0]=m[0],nxtm[1]=m[1]; nxtm[k^1]=idx[t[0]][t[1]][t[2]][t[3]]; if(vis[nxtm[0]][nxtm[1]][k^1]) continue; if(!win[m[0]][m[1]][k]) win[nxtm[0]][nxtm[1]][k^1]=vis[nxtm[0]][nxtm[1]][k^1]=true, dfs(nxtm,k^1); else { if(++cnt[nxtm[0]][nxtm[1]][k^1]==Sum[nxtm[0]]*Sum[nxtm[1]]) vis[nxtm[0]][nxtm[1]][k^1]=true,dfs(nxtm,k^1); } } return; } inline void work() { reg int m[2],k,x; read(k); int t[5];mem(t,0); for(int i=1;i<=8;++i) read(x),++t[x]; m[0]=idx[t[0]][t[1]][t[2]][t[3]]; mem(t,0); for(int i=1;i<=8;++i) read(x),++t[x]; m[1]=idx[t[0]][t[1]][t[2]][t[3]]; puts(vis[m[0]][m[1]][k]?((win[m[0]][m[1]][k]^k)?"Alice":"Bob"):"Deal"); return; } signed main(void) { for(int i=0;i<=8;++i) for(int j=0;i+j<=8;++j) for(int k=0;i+j+k<=8;++k) for(int l=0;i+j+k+l<=8;++l) idx[i][j][k][l]=++idxcnt, rev[idxcnt][0]=i,rev[idxcnt][1]=j,rev[idxcnt][2]=k, rev[idxcnt][3]=l,rev[idxcnt][4]=8-i-j-k-l, Sum[idxcnt]=(!!j)+(!!k)+(!!l)+(!!rev[idxcnt][4]); for(int i=1;i<idxcnt;++i) { vis[idxcnt][i][0]=vis[i][idxcnt][0]= vis[idxcnt][i][1]=vis[i][idxcnt][1]=true; win[idxcnt][i][0]=win[i][idxcnt][1]=true; int m[2]; m[0]=idxcnt,m[1]=i,dfs(m,0),dfs(m,1); m[0]=i,m[1]=idxcnt,dfs(m,0),dfs(m,1); } int t;read(t); while(t--) work(); return 0; }