HDU-2188 悼念512汶川大地震遇難同胞――選拔志願者
阿新 • • 發佈:2022-05-13
悼念512汶川大地震遇難同胞――選拔志願者
巴什博奕
拿到題想了老半天,感覺能超出 n 資金是個坑點,一直想不明白,就暴力打了個表,然後發現複雜度能過就交了,然後過了
後來分析發現“能超出 n 資金”這一條件完全是可有可無
- 如果當前 n mod (m + 1) = 0:
可以直接確定先手必輸,因為後手只要控制好每次都是在 n mod (m + 1) = 0 就行
- 如果當前 n mod (m + 1) != 0:
先手可以將其轉換為第一種情況
所以根據以上分析,先手必勝方完全沒有必要將石子改到 n 以上
打表的方式:
#include <iostream> using namespace std; const int maxn = 1e5 + 20; int sg[maxn], vis[maxn]; void get_sg(int n, int m) { for(int i=0; i<=n; i++) sg[i] = 0; for(int i=1; i<=n; i++) { for(int j=0; j<=m; j++) vis[j] = 0; for(int j=max(0, i-m); j<i; j++) vis[sg[j]] = 1; for(int j=0; j<maxn; j++) { if(vis[j] == 0) { sg[i] = j; break; } } } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--) { int n, m; cin >> n >> m; get_sg(n, m); // for(int i=0; i<=n; i++) cout << i << " sg: " << sg[i] << endl; bool flag = sg[n] != 0; for(int i=max(0, n - m); !flag && i<n; i++) if(sg[i] == 0) flag = true; if(flag) cout << "Grass" << endl; else cout << "Rabbit" << endl; } return 0; }
直接取餘分析:
#include <iostream> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--) { int n, m; cin >> n >> m; if(n % (m + 1) == 0) cout << "Rabbit" << endl; else cout << "Grass" << endl; } return 0; }