CF1382B - Sequential Nim 題解
阿新 • • 發佈:2020-07-23
先特判所有數都為 \(1\) 或都不為 \(1\) 的情況。
- 所有數都為 \(1\):判斷奇偶性;
- 所有數都不為 \(1\):先手必勝,原因略。
對於其餘情況,正難則反。
設 \(\text{flag}_i=1/2\) 為取走第 \(i\) 堆中的最後一個石頭的人(取完石頭)的編號。
例如,若第 \(2\) 堆中有 \(3\) 個石頭,1 取走前 \(2\) 個,2 取走最後 \(1\) 個,則 \(\text{flag}_2=\textbf{2}\)。
假設 \(\text{flag}_n=1\),即 1 獲勝。
列舉 \(i=n-1,n-2,\cdots,1\)。分類討論:
- 若 \(\text{flag}_{i+1}=1\)
- 若 \(a_i=1\),即第 \(i\) 堆中有 \(1\) 個石頭且第 \((i+1)\) 堆被 1 取完,則第 \(i\) 堆必然被 2 取完。原因略;
- 若 \(a_i>1\),即第 \(i\) 堆中有多於 \(1\) 個石頭且第 \((i+1)\) 堆被 1 取完,則第 \(i\) 堆必然被 1 取完。因為若第 \(i\) 堆被 2 取完,則 2 在取第 \(i\) 堆的時候會取 \((a_i-1)\) 個石頭,而留下 \(1\) 個石頭給 1 取走。這樣先後手關係便和假設矛盾,勝負也隨之逆轉。所以第 \(i\) 堆不可能被 2 取完。
- 若 \(\text{flag}_{i+1}=2\)
列舉過後檢查 \(\text{flag}_1\) 是否為 \(1\) 即得到答案(通過判斷與假設是否矛盾,得到答案)。
時間複雜度線性。
Code:
#include <bits/stdc++.h> using namespace std; const int maxN=100005; int flag[maxN]; int main() { int t; scanf("%d",&t); for (;t;t--) { int n; scanf("%d",&n); vector<int> a(n+1); int one=0; for (int i=1;i<=n;i++) { scanf("%d",&a[i]); if (a[i]==1) one++; } if (!one) puts("First"); else if (one==n) puts(n&1?"First":"Second"); else { flag[n]=1; for (int i=n-1;i;i--) if (flag[i+1]==1) if (a[i]==1) flag[i]=2; else flag[i]=1; else flag[i]=1; puts(flag[1]==1?"First":"Second"); } } }