題意:給你一個n和k,在給你一個由0和1構成的長度爲n的字符串,每次操作你可以選擇一個長度爲k的連續子串,然後將其改變成相同顏色,先將字符串改成相同顏色的人獲勝
題解:當n<=k+1時,先手可以直接翻折成同一顏色,屬於先手必勝,對於n>2*k時,如果先手不能通過一次操作取得勝利,那之後就不會有人獲勝,因爲如果先手不能一次取得勝利,那至少需要兩步獲勝,當n>2*k時,先手總能找到一種方法將步數增加或者保持不變,對於後手同理,當n==k+2時,如果左右兩邊顏色相同或者有一邊從端點顏色數量大於等於n-k那麼對於先手都可以一次取完或者倆端點顏色相同,反之如果取不完那對於後手1來說是必勝的,當n>k+2時,先手必勝的判斷是一樣的,只是倆端點的長度1要大於等於n-k,當先手不能取得必勝時,先手的最佳策略一定是從中間取,然後然倆邊顏色不一樣或者中間段顏色與兩邊不同,這樣就可以避免後手必勝,但是如果不能達到,那後手就是必勝,如果先手達到了後手不能贏的情況,那對於後手來說,自己採取最優策略已經不能獲勝那必然可以通過將先手翻折的那一段翻折成相同顏色以達到先後手置換,最後陷入到誰都無法獲勝的局面;
AC代碼:
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<vector>
#include<iostream>
#include<math.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
const int maxn1=1e9;
int read(){
int x=0,w=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')w=0,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
char x[maxn];
int main( )
{
int n=read(),k=read();
scanf("%s",x);
if(n<=k+1){
printf("tokitsukaze\n");
return 0;
}
else if(n==k+2){
if(x[0]!=x[n-1]){
printf("quailty\n");
return 0;
}
else{
printf("tokitsukaze\n");
return 0;
}
}
int l=1,r=n-2;
for(;l<n-1;l++)
if(x[l-1]!=x[l])
break;
for(;r>0;r--)
if(x[r]!=x[r+1])
break;
if(l-1>r){
printf("tokitsukaze\n");
return 0;
}
if(n>2*k){
int num=l+n-r-1;
num=n-num;
if(x[0]==x[n-1]&&num<=k||k+(n-r-1)>=n||k+l>=n){
printf("tokitsukaze\n");
return 0;
}
else{
printf("once again\n");
return 0;
}
}
else{
int num=l+n-r-1;
num=n-num;
int num1=n-r-1+1,num2=l+1;
num1=n-num1,num2=n-num2;
if(x[0]==x[n-1]&&num<=k||k+(n-r-1)>=n||k+l>=n){
printf("tokitsukaze\n");
return 0;
}
else if(num1<=k&&num2<=k){
printf("quailty\n");
return 0;
}
else{
printf("once again\n");
return 0;
}
}
}