1. 程式人生 > 實用技巧 >CF1117E Decypher the String

CF1117E Decypher the String

互動題。

這題需要一個很精妙的構造,所以寫一篇題解來加深自己的理解。

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;
}