1. 程式人生 > 其它 >題解 模擬賽 【game】

題解 模擬賽 【game】

模擬賽 【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;
}

End