HDU-3951 Coin Game
阿新 • • 發佈:2022-05-13
Coin Game
環形博弈
分兩種情況:
-
k = 1 時,就是一個一個拿,奇數先手勝利,偶數後手勝利
-
k > 1 時,如果先手能全部拿完,則先手勝利,否則後手能全部拿完 或者 將鏈分成長度相等的兩份,易分析 \(sg[i] \oplus sg[i] = 0\),因此此時先手拿到的是必敗態
我居然是完全打表出來才過的,這個思路還是看了別人的題解才出的
#include <iostream> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; int cur = 1; while(t--) { int n, k; cin >> n >> k; cout << "Case " << cur++ << ": "; bool flag = false; if(k == 1) flag = n % 2 == 1; else if(n <= k) flag = true; if(flag) cout << "first" << endl; else cout << "second" << endl; } return 0; }
打表
#include <iostream> #include <algorithm> using namespace std; const int maxn = 1e4 + 10; int sg[maxn], vis[maxn], num[maxn]; void init(int n, int k) { for(int i=0; i<=n; i++) num[i] = 0; for(int i=1; i<=n; i++) { for(int j=0; j<maxn; j++) vis[j] = 0; for(int j=max(0, i-k); j<i; j++) vis[num[j]] = 1; for(int u=1; u<=k; u++) { for(int j=1; j<i-u; j++) { vis[num[j] ^ num[i-u-j]] = 1; } } for(int j=0; j<maxn; j++) { if(vis[j] == 0) { num[i] = j; break; } } } } void solve(int n, int k) { init(n, k); for(int i=0; i<=n; i++) sg[i] = 0; for(int i=1; i<=n; i++) { for(int j=0; j<maxn; j++) vis[j] = 0; for(int j=max(0, i-k); j<i; j++) vis[num[j]] = 1; for(int j=0; j<maxn; j++) { if(vis[j] == 0) { sg[i] = j; break; } } } cout << "k : " << k << endl; for(int i=0; i<=n; i++) cout << i << " sg: " << sg[i] << endl; } int main() { int n, k; while(cin >> n >> k) solve(n, k); return 0; }