真不会交互题的交互题指南

真不会交互题的交互题指南

交互题

交互题是一种需要选手程序与评测机交互完成任务的题目。

常见的情况是选手向评测机询问问题,根据得到的答案推出结果。

而题目一般会限制询问次数来增加难度。

重点:在每一次输出后要刷新缓冲区。可以用 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\) 即可。

参考文献

posted @ 2026-07-26 21:36  Atserckcn  阅读(1)  评论(0)    收藏  举报