真不会交互题的交互题指南
真不会交互题的交互题指南
交互题
交互题是一种需要选手程序与评测机交互完成任务的题目。
常见的情况是选手向评测机询问问题,根据得到的答案推出结果。
而题目一般会限制询问次数来增加难度。
重点:在每一次输出后要刷新缓冲区。可以用 fflush(stdout) 或换行 endl。
分类
- I/O 交互
询问就是输入输出内容。一般是将你的询问输出,然后输入评测机给你的答案。
- 函数交互
就是让你写一个函数,会传参,可以调用题目提供的若干函数,求结果。
题目一般会给个叫做 grader.cpp 的参考测评程序文件。它可以担任临时交互库的角色。
常考的知识点
核心是尽量减少询问的次数。所以要善于排除无用信息,筛选需要询问的优质信息。
- 二分
- 双指针(ABC466C)
- 倍增
- 注意到若干有关单调性的信息
- 分治
- 由已知信息推未知信息
- 随机化
- 人类智慧
本地运行与调试
标准方案
首先下载完题目给的文件后,全放文件夹里。
把这个文件夹的路径复制。例:C:\Users\lenovo\Desktop\hack
然后 win+R,开 cmd,输入:
cd C:\Users\lenovo\Desktop\hack
然后就成功地进入了此目录。
然后题面 PDF 中会给【测试程序方式】。
里面理论上会有一句:选手可以在本题目录下使用如下命令编译得到可执行程序。
例如联合省选 2026 排列游戏的命令就是:
g++ grader.cpp perm.cpp -o perm -std=gnu++14 -O2 -static
然后你照着输入就行了。但这太麻烦力!
野鸡方案
- 对于 I/O 交互:
假设题目:ABC466C.
假设代码为:
#include<bits/stdc++.h>
using namespace std;
typedef long long ljl;
const int N=1e3+5;
int n;
ljl ans;
string s;
bool getans(int l,int r)
{
cout<<"? "<<l<<' '<<r<<endl;
cin>>s;
return s=="Yes";
}
int main(){
cin>>n;
for(int l=1,r=2;l<n;++l)
{
r=max(l+1,r);
while(l<r&&r<=n&&getans(l,r))++r;
ans=ans+(r-1-l);
}
cout<<"! "<<ans<<endl;
return 0;
}
首先自己写一个随机数程序。每次随机生成所有数字的坐标,例如:
const int N=5005;
double a[N];
mt19937 rd(time(nullptr));
void init()
{
for(int i=1;i<=n;++i)
a[i]=a[i-1]+(rd()%1000)/1000;
return;
}
然后自己写询问程序:
string query(int l,int r)
{
if(s[r]-s[l]<=1.0)return "Yes";
return "No";
}
手动另开一个 cpp 文件,将所有东西复制过去,有机结合一下。
#include<bits/stdc++.h>
using namespace std;
typedef long long ljl;
const int N=1e3+5;
double a[N];
mt19937 rd(time(nullptr));
int n;
ljl ans;
string s;
void init()
{
for(int i=1;i<=n;++i)
a[i]=a[i-1]+(rd()%1000)/1000;
return;
}
string query(int l,int r)
{
if(s[r]-s[l]<=1.0)return "Yes";
return "No";
}
bool getans(int l,int r)
{
// cout<<"? "<<l<<' '<<r<<endl;
// cin>>s;
s=query(l,r);//在调试时代替上面两行,提交时要换回去
return s=="Yes";
}
int main(){
cin>>n;
init();
for(int l=1,r=2;l<n;++l)
{
r=max(l+1,r);
while(l<r&&r<=n&&getans(l,r))++r;
ans=ans+(r-1-l);
}
cout<<"! "<<ans<<endl;
return 0;
}
注意我注释的那几行。
然后再自己随便写一个暴力程序,将随机出来的 \(a\) 值输出,然后 init() 函数改为读入就行了。
然后就可以像传统题那样对拍了。
- 函数式交互
题目:猜数。
代码(需要提交的):
extern "C" int Seniorious(int x);
extern "C" int Chtholly(int n,int c)
{
int l=1,r=n;
while(l<r)
{
int mid=(l+r)/2;int s=Seniorious(mid);
if(!s)return mid;
if(s==1)r=mid-1;
if(s==-1)l=mid+1;
}
return l;
}
老规矩,新开 cpp,然后手打 Seniorious 函数。然后有机杂交。
#include<bits/stdc++.h>
using namespace std;
int n,c,ans;
mt19937 rd(time(nullptr));
extern "C" int Seniorious(int x);
extern "C" int Chtholly(int n,int c)
{
int l=1,r=n;
while(l<r)
{
int mid=(l+r)/2;int s=Seniorious(mid);
if(!s)return mid;
if(s==1)r=mid-1;
if(s==-1)l=mid+1;
}
return l;
}
int main()
{
cin>>n>>c>>ans;//这里输入
cout<<Chtholly(n,c)<<endl;//还可以记录询问了多少次等信息
return 0;
}
extern "C" int Seniorious(int x)//这是手打的
{
if(x==ans)return 0;
if(x>ans)return 1;
return -1;
}
然后对拍就随机 \(n,c,ans\) 即可。

浙公网安备 33010602011771号