【Educational Codeforces Round 60 (Rated for Div. 2) E. Decypher the String】交互


E. Decypher the String

题意

就是给你一个长度为n的字符串的转换规则,规则是最多可以交换任意两个位置n次,得到新的字符串,现在给你一个转换之后的字符串,让你求原来的字符串。
最多提问三次,每次提问你给出一个长度为n的字符串,交互会按照规则返回转换之后的字符串。

1 ≤ n ≤ 1 0 4 1 \leq n \leq 10^4 1n104
做法

这道题不考虑那个转换规则,我们只知道最后每个位置一定由之前字符串的某个位置而来,而且是一一对应的。所以我们只要知道每个字符之前在哪个位置就可以,我们第一次提问用一个
26 ∗ 26 ∗ a , 26 ∗ 26 ∗ b , 26 ∗ 26 ∗ c . . . . . 26 ∗ 26 ∗ z 26*26*a,26*26*b,26*26*c.....26*26*z 2626a,2626b,2626c.....2626z 这样的字符串提问,我们就知道每个字符来自哪一个块中,之后再用 26 ∗ a , 26 ∗ b , 26 ∗ c . . . . 26 ∗ z 26*a,26*b,26*c....26*z 26a,26b,26c....26z这样的字符串提问,就知道这个字符来自哪一个小块,因为之前确定大块,而每个大块只包含26种小块,所以可以根据答案判断这个位置来自哪个大块的哪个小块。同理最后用 a , b , c , d . . . z a,b,c,d...z a,b,c,d...z去提问,就知道每个字符来自哪个位置了,其实仔细想一下就是一个26进制。因为 2 6 3 > 10000 26^3>10000 263>10000 ,所以每个位置都有唯一的对应关系。
代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<map>
using namespace std;
const int maxn = 1e5+5;
char str[maxn],tmp[maxn];
char ans[3][maxn];
char rrs[3][maxn];
map<string,int> mp;
char ou[maxn];
int main()
{
    scanf("%s",tmp);
    int len=strlen(tmp);
    for(int i=0;i<len;i++)
    {
        ans[0][i]=char(i/(26*26)+'a');
        ans[1][i]=char((i%(26*26))/26+'a');
        ans[2][i]=char(i%26+'a');
        string res="";
        res+=ans[0][i];
        res+=ans[1][i];
        res+=ans[2][i];
        mp[res]=i;//i位置三次查询串的字符为res
    }
    for(int i=0;i<3;i++) ans[i][len]='\0';
    cout<<"?"<<" "<<ans[0]<<endl;
    scanf("%s",str);
    for(int i=0;i<len;i++) rrs[0][i]=str[i];
    cout<<"?"<<" "<<ans[1]<<endl;
    scanf("%s",str);
    for(int i=0;i<len;i++) rrs[1][i]=str[i];
    cout<<"?"<<" "<<ans[2]<<endl;
    scanf("%s",str);
    for(int i=0;i<len;i++) rrs[2][i]=str[i];
    for(int i=0;i<len;i++)
    {
        string res="";
        res+=rrs[0][i];
        res+=rrs[1][i];
        res+=rrs[2][i];
        ou[mp[res]]=tmp[i];
    }
    ou[len]='\0';
    cout<<"!"<<" "<<ou<<endl;
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值