题目传送门


分析

先尝试锁定一个字母,显然询问 \(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. [超实用插件]在Visual Studio中查看EF Core查询计划

    前言 EF Core是我们.NET开发中比较常用的一款ORM框架,今天我们分享一款可以直接在Visual Studio中查看EF Core查询计划调试器可视化工具(帮助开发者分析和优化数据库查询性能) ...

  2. 【Azure Service Bus】使用Spring Cloud integration示例代码,为多个 Service Bus的连接使用 ConnectionString 方式

    问题描述 查看Service Bus的Java示例代码,发现使用Spring Cloud Integration,配置 Application.yaml 可以连接到两个Service Bus. 但代码 ...

  3. 批量删除mysql库中数据

    -- 查询构建批量删除表语句(根据数据库名称) select concat('delete from ', TABLE_NAME, ' where org_id = "<条件id> ...

  4. vue3自定义Hooks

    比较简单的小demo,直接上代码吧 ts使用defineComponent,setup()里面使用 Composition API 写法,逻辑块清晰,不用前后文查找,拒绝 spaghetti code ...

  5. JAVA 多线程---面经

    线程与进程 提到进程那就要说程序,程序有指令和数据,程序从磁盘加载到内存,cpu获得指令进行执行,其中还会用到各种资源如网络资源,磁盘等.一个程序从磁盘进入内存,就是进程实例的创建. 一个程序可以有多 ...

  6. Python笔记六之多进程

    本文首发于公众号:Hunter后端 原文链接:Python笔记六之多进程 在 Python 里,我们使用 multiprocessing 这个模块来进行多进程的操作. multiprocessing ...

  7. obs 录制教程 手机录屏用 向日葵 手机投屏 能用有线用有线的连接

    obs 录制教程 手机录屏用 向日葵 手机投屏 稍微有点卡 华为手机有个投屏 笔记本不支持这个 miracast 淘宝有卖 投屏设备的,搜 miracast 100多米 免费的就用向日葵就得了. 最新 ...

  8. koa-generator - koa 脚手架

    koa-generator - koa 脚手架 npm install -g koa-generator 创建 koa2 /tmp/foo && cd /tmp/foo 资料: 基于N ...

  9. Java | zuul 1.x 是如何实现请求转发的

    zuul 1.x 是如何实现请求转发的 文档写的再好,也不如源码写的好 源码地址: GitHub: https://github.com/Netflix/zuul Gitee: https://git ...

  10. Java中float和double的精度

    比较基本类型double和float和某一个数是否相等的时候,不要用==或>=或<=,因为double和float都是有精度问题的,计算机只能保存一定位数的小数,这就会存在精度问题. 下面 ...