题目传送门


分析

先尝试锁定一个字母,显然询问 \(CH,CO,CC\) 会比直接询问 \(C\) 更优,虽然牺牲了最后一个位置是否为 \(C\) 的查询。

同理,询问 \(HH,OH,CH\) 会比直接询问 \(H\) 更优,虽然牺牲了第一个位置是否为 \(H\) 的查询。

可以发现这样询问非首尾位置未填的一定是 \(O\),\(C,H\) 一定会被询问出来。

然后首字母只可能填 \(O,H\),尾字母只可能填 \(C,O\),然后再三次判断就可以知道整个串(如果三次判断都不知道,那只能是最后一种情况)

那么操作代价就是 \(\frac{5}{4}+\frac{4-1}{n^2}\),可以发现在 \(n>4\) 时都不超过 \(\frac{7}{5}\),\(n=5\) 时最小,为 \(1.37\)

那么只剩下 \(n=4\) 的情况,显然直接这样问肯定会代价过高。

可以发现只要确定其中两个位置,就可以花不超过 \(\frac{9-1}{16}\) 的代价确定其它位置,

还是尝试锁定 \(C\) 字母,如果锁定得了那么只需要花 \(\frac{3}{4}\) 的代价,

同时其它位置就可以花不超过 \(\frac{6-1}{16}\) 的代价,合起来就是 \(\frac{17}{16}\)

如果 \(C\) 字母不能锁定,再询问 \(OH\),同理,只需要花 \(\frac{4}{4}+\frac{6-1}{16}=\frac{21}{16}\) 的代价。

再询问 \(HH\),如果 \(H\) 被锁定,其实第一二位一定是 \(H\),如果不是那么它在之前一定会被询问出来。

如果第三四位没有被询问出来,那么第三位一定是 \(O\),否则第三位一定被询问出来,

同理只需要确定尾位,需要 \(\frac{5}{4}+\frac{1}{16}=\frac{21}{16}\)。

最后一种情况,中间两位一定是 \(O\),最后询问 \(OOO\),通过 \(\frac{5}{4}+\frac{1}{9}=\frac{49}{36}\) 就可以确定所有位置啦


代码

#include <iostream>
using namespace std;
const char ch[3]={'H','O','C'};
int k,x,Test,n,AC; char S[51];
void doit(char ch,char Ch){
cout<<"? "<<ch<<Ch<<endl;
cin>>k;
for (int i=0;i<k;++i)
cin>>x,S[x]=ch,S[x+1]=Ch;
}
void answ(int t){
bool flag=1;
if (S[1]=='\0'&&S[n]=='\0'){
for (int o=2;o>=t&&flag;--o)
for (int j=0;j<2&&flag;++j)
if (!t||o!=1||j!=1){
S[1]=ch[j],S[n]=ch[o],cout<<"? ";
for (int i=1;i<=n;++i) cout<<S[i]; cout<<endl;
cin>>k;
if (k) cin>>x,flag=0;
}
if (flag) S[1]=S[n]='O',flag=0;
}
for (int i=1;i<n&&flag;++i)
if (S[i]=='\0'&&S[i+1]=='\0'){
for (int o=0;o<3&&flag;++o)
if (!t||o<2||i==n-1)
for (int j=0;j<2&&flag;++j){
S[i]=ch[j],S[i+1]=ch[o],cout<<"? ";
for (int i=1;i<=n;++i) cout<<S[i]; cout<<endl;
cin>>k;
if (k) cin>>x,flag=0;
}
flag=0; break;
}
if (flag){
for (int i=1;i<=n;++i)
if (S[i]=='\0'){
for (int o=0;o<3&&flag;++o) if (!t||o<2||i==n){
S[i]=ch[o],cout<<"? ";
for (int i=1;i<=n;++i) cout<<S[i]; cout<<endl;
cin>>k;
if (k) cin>>x,flag=0;
}
}
}
cout<<"! ";
for (int i=1;i<=n;++i) cout<<S[i];
cout<<endl;
}
int main(){
ios::sync_with_stdio(0);
for (cin>>Test;Test;--Test){
cin>>n;
if (n>4){
for (int i=0;i<3;++i) doit('C',ch[i]);
doit('H','H'),doit('O','H');
for (int i=2;i<n;++i) if (S[i]=='\0') S[i]='O';
answ(1);
}else{
for (int i=0;i<3;++i) doit('C',ch[i]);
if (S[2]!='\0'||S[3]!='\0') answ(0);
else{
doit('O','H');
if (S[2]!='\0'||S[3]!='\0') answ(0);
else{
doit('H','H');
if (S[2]!='\0'){
if (S[4]=='\0'){
if (S[3]=='\0') S[3]='O';
cout<<"? ";
for (int i=1;i<4;++i) cout<<S[i];
cout<<'C'<<endl;
cin>>k;
if (k) cin>>x,S[4]='C';
else S[4]='O';
}
cout<<"! ";
for (int i=1;i<=4;++i) cout<<S[i];
cout<<endl;
}else{
S[2]=S[3]='O';
cout<<"? OOO"<<endl;
cin>>k;
if (k==2) cin>>x,cin>>x,S[1]=S[4]='O';
else if (k==1){
cin>>x,S[x]=S[x+2]='O';
if (S[1]=='\0') S[1]='H';
else S[4]='C';
}else S[1]='H',S[4]='C';
cout<<"! ";
for (int i=1;i<=4;++i) cout<<S[i];
cout<<endl;
}
}
}
}
for (int i=1;i<=n;++i) S[i]='\0';
cin>>AC;
}
return 0;
}

#交互,分类讨论#CF1292E Rin and The Unknown Flower的更多相关文章

  1. Codeforces 460D Little Victor and Set --分类讨论+构造

    题意:从区间[L,R]中选取不多于k个数,使这些数异或和尽量小,输出最小异或和以及选取的那些数. 解法:分类讨论. 设选取k个数. 1. k=4的时候如果区间长度>=4且L是偶数,那么可以构造四 ...

  2. BZOJ-1067 降雨量 线段树+分类讨论

    这道B题,刚的不行,各种碎点及其容易忽略,受不鸟了直接 1067: [SCOI2007]降雨量 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 2859 ...

  3. UVaLive 6862 Triples (数学+分类讨论)

    题意:给定一个n和m,问你x^j + y^j = z^j 的数量有多少个,其中0 <= x <= y <= z <= m, j = 2, 3, 4, ... n. 析:是一个数 ...

  4. 枚举(分类讨论):BZOJ 1177: [Apio2009]Oil

    1177: [Apio2009]Oil Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1477  Solved: 589[Submit] Descri ...

  5. Educational Codeforces Round 63 (Rated for Div. 2) D. Beautiful Array 分类讨论连续递推dp

    题意:给出一个 数列 和一个x 可以对数列一个连续的部分 每个数乘以x  问该序列可以达到的最大连续序列和是多少 思路: 不是所有区间题目都是线段树!!!!!! 这题其实是一个很简单的dp 使用的是分 ...

  6. 【cf789B】Masha and geometric depression(分类讨论/暴力)

    B. Masha and geometric depression 题意 在黑板上写数列,首项是b,公比是q,超过l时就停止不写.给定m个数,遇到后跳过不写.问一共写多少个数,如果无穷个输出inf. ...

  7. P2331 [SCOI2005]最大子矩阵 (动规:分类讨论状态)

    题目链接:传送门 题目: 题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k( ...

  8. UVa 11722 Joining with Friend (几何概率 + 分类讨论)

    题意:某两个人 A,B 要在一个地点见面,然后 A 到地点的时间区间是 [t1, t2],B 到地点的时间区间是 [s1, s2],他们出现的在这两个区间的每个时刻概率是相同的,并且他们约定一个到了地 ...

  9. Bzoj4558:分类讨论 计算几何 组合数学

    国际惯例的题面: 这题让我爆肝啦......这种计数显然容斥,正好不含任何坏点的我们不会算,但是我们能算至少含零个坏点的,至少含一个坏点的,至少含两个坏点的......所以最终的答案就是(至少含零个坏 ...

  10. HDU 5203 Rikka with wood sticks 分类讨论

    题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5203 bc(chinese):http://bestcoder.hdu.edu.cn/con ...

随机推荐

  1. 【Android 逆向】frida 检测绕过

    1. aaa.apk 安装到手机,是一个叫玩吧的应用 ./hooker ...... 23248 浏 览 器 com.browser2345_oem 32541 玩吧 com.wodi.who 244 ...

  2. [BUUCTF][Web][极客大挑战 2019]EasySQL 1

    打开靶机对应的url 界面显示需要输入账号和密码 分别在两个输入框尝试加单引号尝试是否有sql注入的可能,比如 123' 发现两个框可以注入,因为报了个错误信息 You have an error i ...

  3. Qt三方库开发技术:QXlsx介绍、编译和使用

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  4. 项目实战:Qt+FFmpeg录屏应用(支持帧率、清晰度设置)

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109827936各位读者,知识无穷而人力有穷,要 ...

  5. 项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端

    需求   1.Qt已经开发了应用,封装成Qt库,以供C#调用.  2.Qt的tcp客户端封装,以供C#调用,双向传递数据.   原理   1.使用QtCreator编译msvc版本的Qt库:  2.使 ...

  6. centos7.x及centos8.x安装新版docker

    前置步骤 # 如之前安装过docker,请先删除 yum remove docker docker-common docker-selinux docker-engine centos7 # cent ...

  7. C C++指针面试题零碎整理

    最基础的指针如下: int a; int* p = &a; 答:p指向a的地址,&是取a的地址.*指的是指针中取内容的符号. 2.str[]和str*的区别: char str1[] ...

  8. 大众点评cat报警源码

    类时序 时许说明 判断是否是报警机器. 1分钟启动一个线程根据设置的报警条件,时间段去查询CAT报告数据. 根据返回的报告数据,逐层解析TYPE,NAME,RANGE中的数据是否满足报警条件. 只有全 ...

  9. 解决网页无法复制粘贴选中的问题 显示vip无法复制解决方案

    方法:先是按F12打开控制台点击console输入以下代码!!!! 解决网页禁止鼠标右键,无法被选中的 第一种: javascript:(function() { function R(a){ona ...

  10. Redis之数据持久化小结

    一.概述 Redis作为内存型的数据库,虽然很快,依然有着很大的隐患,一旦服务器宕机重启,内存中数据还会存在吗? 很容易想到的一个方案是从后台数据恢复这些数据,如果数据量很小,这倒是一个可行的方案.但 ...