Solution
不妨记 A 为先手 Tokitsukaze,B 为后手 Quailty。记 \(f(X)\) 为 \(X\) 这个人最终的状态(胜、平、负分别为 \(1,0,-1\))。
首先特判掉全 0 和全 1 的情况。
不妨设字符串中第一个 0 在 \(l_0\),最后一个 0 在 \(r_0\),\(l_1,r_1\) 同理。
首先判掉比较平凡的情况。如果 \(r_0-l_0+1\le k\) 或 \(r_1-l_1+1\le k\) 那么 A 可以一步获胜。再判掉 A 无论如何操作后 B 都能一步取胜的情况。
此时博弈一定不会在 2 步内结束。B 至少 可以通过不断重复 A 的操作,使得操作后局面不变,把无法一步取胜 的状态传递回 A,从而至少达到平局 ,即 \(f(B)\ge 0\)。同理 A 也可以在第一步后不断重复 B 的操作使 \(f(A)\ge 0\)。又因为零和博弈 \(f(A)+f(B)=0\),最终只能平局。
Code
cpp
#include <bits/stdc++.h>
using namespace std;
int n,k;
string s;
signed main(){
cin.tie(0)->sync_with_stdio(0);
cin>>n>>k>>s;
if(s[0]=='1') for(char &c:s) c^=1; // 令s[0]='0'
// 特判全0/全1
if(s.find('0')==s.npos||s.find('1')==s.npos){
cout<<"tokitsukaze\n";
return 0;
}
int l0=s.find('0'),r0=s.rfind('0');
int l1=s.find('1'),r1=s.rfind('1');
// A一步取胜
if(r0-l0+1<=k||r1-l1+1<=k){
cout<<"tokitsukaze\n";
return 0;
}
// A无论如何操作后B都能一步取胜
if(r0<l1){ // 000111
if(k>min(r0-l0+1,r1-l1+1)&&n-k<k){
cout<<"quailty\n";
return 0;
}
}
if(l0<l1&&r1<r0){ // 0001...1000
if(k>=n-1){
cout<<"quailty\n";
return 0;
}
}
if(l0<l1&&r0<r1&&r0>l1){ // 0001...0111
int bound=max(r0-l0-1,r1-l1-1);
if(k>bound){
cout<<"quailty\n";
return 0;
}
}
// 平局
cout<<"once again\n";
return 0;
}