題解 模擬賽 【game】
阿新 • • 發佈:2021-08-09
模擬賽 【game】
題目大意:
solution:
我們發現個位數時小 \(Q\) 是必勝的,那麼能到個位數的數小 \(Q\) 是比輸的,因為小 \(Q\) 操作後小 \(L\) 就會拿掉個位數,然後贏得遊戲。那麼我們現在就有了一個遞推策略:
設 \(f_i\) 為數字 \(i\) 小 \(Q\) 是否必勝,\(Fx_i\) 為數字 \(i\) 最大數碼, \(Fm_i\) 為數字 \(i\) 最小數碼(除 \(0\) )。
如果 \(f_{i-Fx_i}\) 和 \(f_{i-Fm_i}\) 都必勝,那麼 \(f_i\) 必輸,否則 \(f_i\) 必勝。
預處理一下就好了。
細節處理:
- 最小數碼不包括 \(0\) 。
程式碼
#include<cstdio> using namespace std; const int N=1e6+5; bool f[N]; inline int Fx(int x){//求最大數碼 int res=0; while(x){ if(x%10>res) res=x%10; x/=10; } return res; } inline int Fm(int x){//求最小數碼不包括0 int res=10; while(x){ if(x%10<res&&x%10!=0) res=x%10;//! x/=10; } return res; } inline void init(){ for(int i=1;i<10;i++) f[i]=1;//個位數都必勝 for(int i=10;i<=1000000;i++){//遞推 if(f[i-Fx(i)]&&f[i-Fm(i)]) f[i]=0; else f[i]=1; } } int main(){ init(); int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); if(f[n]) puts("Yes"); else puts("No"); } return 0; }