[loj2863] [ioi2018 d1t1] combo - 有趣的交互題

傳送門:https://loj.ac/problem/2863

斗膽來一發ioi題解。

今年的d1t1是一道交互題。喜歡出交互題是ioi的一大特色之一,而國內的正式比賽中還是很少見到交互題的身影的(印象中只有wc2016和wc2018有交互題)。

雖是ioi,但難度不算大的題還是會出現的,主要也是要考慮到世界各國選手的整體水平。本題算是今年6道題中最簡單的一道,全場大約有一半的選手都成功ac。

題目大意:有一個字符串s,長度n<=2000,由4種字符“A”“B”“X”“Y”組成,保證第一個字符在後面不再出現。你可以向交互庫詢問一個自己指定的字符串p(p的長度不超過n*4且也是由上述4種字符組成),交互庫會返回一個非負整數x,表示最長的、既是s的前綴、也是p的子串的串長。要求用不超過n+2次詢問確定串s。

看到這個題,首先可以想到:這個奇怪的限制“保證第一個字符在後面不再出現”是幹什麼用的?容易想到我們可以用第一個字符作爲“天然的分隔符”,在p串中一次性塞入若干可能的結果來進行猜測。

容易想到的一種解法是,如果已知長度爲x的前綴(記做q),我們可以用2次操作,問出第x+1個字符:

首先令p=qAqB,如果詢問結果=x+1,說明下一個字符是A或B,於是再詢問p=qA,根據結果是x還是x+1就可以確定下一個字符;同樣地,如果第一次詢問得到x,說明下一個字符是X或Y,同樣也可以再詢問一次得到結果。

這樣詢問次數=2n,能不能更給力些?

要做到n+2次詢問,說明我們要做到1次詢問得到1位的結果,當然我們會發現問出第1位和最後一位的話兩次詢問是無法避免的。

首先,既然第一個字符不會重複出現,我們下面的詢問就只是3選1,而不是4選1。下面不妨設首位是Y,後面的可選項是A,B,X吧。

然後,我們相當於每次要構造一個p,使得可能會有3種不同的回答,分別對應下一個字符的3種情況。

3種回答顯然只能是x,x+1,x+2,因爲x-1之類的回答沒有任何意義。

我們可以讓p中有一個qA,用x+1表示A,然後不加入形如qB的串,則x就是B,那x+2呢?

如果要讓X時答案是x+2,就意味着必須在qX後面再匹配一位,而後一位我們不知道,咋辦?

此時我們就要利用|p|<=4n的性質。直接枚舉下一位!

也就是說,p=qAqBAqBBqBC,此時恰好滿足我們的要求。

於是問題被完美解決了。幹得漂亮!

//注:以下代碼根據ioi提交格式編寫

#include<bits/stdc++.h>
using namespace std;
#include"combo.h"
string as,p;
void wk(char a,char b,char c,int n){
	for(int i = 2;i < n;++i){
		p = as + a + as + b + a + as + b + b + as + b + c;
		int j = press(p);
		if(j == i - 1) as += c;
		else if(j == i) as += a;
		else as += b;
	}
	if(press(as + a) == n) as += a;
	else if(press(as + b) == n) as += b;
	else as += c;
}
string guess_sequence(int n){
	if(press("AB")){
		if(press("A")) as = "A";
		else as = "B";
	}
	else{
		if(press("X")) as = "X";
		else as = "Y";
	}
	if(n == 1) return as;
	if(as == "A") wk('B','X','Y',n);
	else if(as == "B") wk('A','X','Y',n);
	else if(as == "X") wk('A','B','Y',n);
	else wk('A','B','X',n);
	return as;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章