题目传送门


分析

先尝试锁定一个字母,显然询问 \(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. SpringBoot使用令牌桶算法+拦截器+自定义注解+自定义异常实现简单的限流

    令牌桶 在高并发的情况下,限流是后端常用的手段之一,可以对系统限流.接口限流.用户限流等,本文就使用令牌桶算法+拦截器+自定义注解+自定义异常实现限流的demo. 令牌桶思想 大小固定的令牌桶可自行以 ...

  2. 案例分享:某品牌音响系列协议调试工具(搜寻主机,查询通道,基本控制API,云音乐API,语言节目API等,可增删改指令)

    需求   某音响品牌需要一套完整的协议调试工具,提供给研发人员,渠道商,客户,现场人员等使用:  1.使用sqlite3数据库存储协议,  2.搜寻主机,操作主机:  3.探测云端API,调试API: ...

  3. 可视化技术在 Nebula Graph 中的应用

    本文首发于 Nebula Graph Community 公众号 本文整理自 #可视化 on Live 主题直播,在本期直播中 3 位可视化嘉宾讲述了他们眼中的可视化,以及他们在可视化项目实践中踩过的 ...

  4. CPack 入门指南

    背景 CPack 是 CMake 2.4.2 之后的一个内置工具,用于创建软件的二进制包和源代码包. CPack 在整个 CMake 工具链的位置. CPack 支持打包的包格式有以下种类: 7Z ( ...

  5. PHP项目&TP框架&SQL&XSS&架构&路由&调试&写法

    开发基础-TP框架-入口&调试&路由&写法等 参考手册-TP5开发手册-为了掌握了解框架 首页文件看APP_PATH定义-为了后期分析核心代码 全局搜索:THINK_VERSI ...

  6. 在.Net中使用Java代码?

    前言 你没有看错,我确实在.Net6的项目中在编写java,我都using java了,算不算在写java那? using com.microsoft.sqlserver.jdbc; using ja ...

  7. Python列表转换成字典、嵌套列表转字典、多个列表转为字典嵌套列表

    目录 两列表转为字典 多列表转为字典嵌套列表 嵌套列表转字典 方法一:直接内置dict 方法二: for循环 一个列表转字典 两列表转为字典 list1=["key1"," ...

  8. 使用PdfSharp从模板生成Pdf文件

    ​ 最近在做一个生成文档的需求.通过先制作一个包含各字段占位符的文档模板,导入这个模板并填写内容替换掉占位符,再输出成最终文件. 由于版式固定,安全性更好,业务上常用Pdf作为最终标准化的格式, 在. ...

  9. 制作B站直播简介

    本文只用于个人总结备份,如果对你有帮助就更好了. 准备工作 准备好简介要用的的背景图.头像图,上传到图床生成图片链接. 简介的内容可分为主播简介.直播时间.直播内容.联系方式,内容根据实际需要修改,需 ...

  10. Python 的结构体函数 struct pack, unpack 用法详解

    一 python 结构体 * python struct 模块可以用来在存储二进制文件,广泛用在文件系统,网络连接领域. *  它可以用在c语言和python语言之间的数据的格式转换. 二  Pyth ...