Educational Codeforces Round 60 (Rated for Div. 2) E. Decypher the String
題目大意:這是一道交互題。給你一個長度為n的字符串,這個字符串是經過規則變換的,題目不告訴你變換規則,但是允許你提問3次:每次提問你給出一個長度為n的字符串,程序會返回按變換規則變換後的字符串,提問3次後你需要猜出這個字符串。解法是學習https://blog.csdn.net/baiyifeifei/article/details/87807822 這個博主的,借用了進制的思想非常巧妙。
解法:對於某個位置的來源位置我們設為x,因為26*26*26>10000,那麽x可以唯一表示為x=a*26*26+b*26+c。那麽我們只要想辦法求出a,b,c就能得到它的來源位置。
那麽怎麽利用三次詢問求a,b,c?我們首先構造(26*26個a) (26*26個b) (26*26個c)......(26*26個z),設此位置變換後的字符為c[0],那麽a=c[0]-‘a‘(可以理解為a=x/(26*26)=c[0]-‘a‘)。道理類似的我們下一次構造(26個a) (26個b) (26個c) ......(26個d)的字符串讓程序變換,此時變換後的字符為c[1],那麽b=c[1]-‘a‘(可以理解為b=x%(26*26) /26=(b*26+c)/26=c[1]-‘a‘),這裏的b可能有點兒難理解,為什麽是這樣得到的c[1]就是(b*26+c)/26?因為前一個詢問我們已經確定x在a這一個(26*26)的大塊裏面了,那麽我們只需要考慮這個大塊,把這個大塊再細分為26塊看看返回什麽值就能知道x在a這個大塊的哪一個小塊b裏面。道理類似的最後構造(abc..z)(abc..z)...(abc..z)得到c=c[2]-‘a‘。
那麽我們就得到該位置的來源是a*26*26+b*26+c,問題得到解決。
如果還是感覺難以理解,可以看看代碼再仔細想想:
#include<bits/stdc++.h> using namespace std; const int N=10000+10; int n; char s[N],q[3][N],g[3][N],ans[N]; int main() { scanf("%s",s); n=strlen(s); for (int i=0;i<n;i++) { q[0][i]=(i/(26*26)%26+‘a‘); q[1][i]=(i/26%26+‘a‘); q[2][i]=(i%26+‘a‘); } for (int i=0;i<3;i++) { printf("? %s\n",q[i]); fflush(stdout); scanf("%s",g[i]); } for (int i=0;i<n;i++) { int tmp=(g[0][i]-‘a‘)*26*26+(g[1][i]-‘a‘)*26+(g[2][i]-‘a‘); ans[tmp]=s[i]; } printf("! %s",ans); return 0; }
Educational Codeforces Round 60 (Rated for Div. 2) E. Decypher the String