CF1117E Decypher the String
阿新 • • 發佈:2020-09-21
互動題。
這題需要一個很精妙的構造,所以寫一篇題解來加深自己的理解。
Solution
如果直接看見 \(3\) 次機會和 \(10000\) 的 \(|s|\) 可能會很迷茫,但是還有一個 \(26\) ,那我們就可以瞎寫一個 \(26^2<10000<26^3\) ,然後就到了精妙的構造了。
第一次機會:
\(aaa...aaa(26*26)bbb...bbb(26*26)ccc...ccc(26*26)...\)
每一個 \(26*26\) 是大塊
第二次機會:
\(aaa...aaa(26)bbb...bbb(26)ccc...ccc(26)...\)
每一個 \(26\) 是小塊
第三次機會:
\(abcdefg...xyzabcdefg...xyz...\)
這樣對於變化後的串 \(s’\) 的每一位都可以找到大塊中的小塊中的準確位置,即整個原串。
(或者這樣理解:將 \(s'\) 拆開,三次操作相當於找到位置 \(i\) 所對應的26進位制數)
程式碼
#include<bits/stdc++.h> using namespace std; const int N=10005; int pos[N]; string s,print,res; char ans[N]; int main(){ cin>>res; int len=res.size(); print="? "; char ch='a'; //先分成26*26的大塊,確定在大塊的位置 for(int i=0;i<len;i++){ print+=ch; if((i+1)%(26*26)==0) ch++; } cout<<print<<endl; cin>>s; for(int i=0;i<len;i++) pos[i]+=(s[i]-'a')*26*26; ch='a'; print="? "; //分成26的小塊,確定在小塊的位置 for(int i=0;i<len;i++){ print+=ch; if((i+1)%26==0) ch++; if(ch=='z'+1) ch='a'; } cout<<print<<endl; cin>>s; for(int i=0;i<len;i++) pos[i]+=(s[i]-'a')*26; ch='a'; print="? "; //分成1,確定最終的位置 for(int i=0;i<len;i++){ print+=ch; ch++; if(ch=='z'+1) ch='a'; } cout<<print<<endl; cin>>s; for(int i=0;i<len;i++) pos[i]+=(s[i]-'a'); for(int i=0;i<len;i++) ans[pos[i]]=res[i]; printf("! %s",ans); fflush(stdout); return 0; }