CF1137D题解
神仙交互题
记得以前听lch神仙讲过,不过当时还没做过这道题
题意(来自yyb神仙的翻译):
有一张图是由一个长度为\(t\)的链和一个大小为\(c\)的环中间连上一条边组成的。
假如这条边连接的是链的右端点,和环上的T点。
令链的左端点是S。
现在在S处有\(10\)个棋子,编号\(0−9\),每次你可以让任意数量的棋子向出边方向走一步,交互库会返回若干个集合,每一个集合内的棋子都在同一个位置上,并且这个位置上的所有棋子都在这个集合中。
现在你既不知道\(t\)也不知道\(c\)。你需要使用不超过\(3(t+c)\)次操作使得所有棋子都移动到T位置上并且返回交互库
官方题解翻译......(手动翻译,不是机翻)
棋子的数量在这里是迷惑你的,其实只需要三个棋子就可以解决问题
我们把移动速度快的棋子叫做\(fast\),慢的叫\(slow\),\(slow\)每走一步,\(fast\)走两步,当他们相遇时停止
显然,\(slow\)无法在环上走完完整的一圈,因为\(slow\)每走1圈,\(fast\)走两圈,一定会被\(fast\)追上
故他们相遇时行走的距离\(slow=t+x\),\(fast=t+x+k*c\),且\(fast=2*slow\)
解得\(x≡-t(mod c)\)
所以再走t步就能到达终点了,但我们不知道t是多少,注意到留在原点的棋子离终点距离刚好为t,故让所有棋子同时走,相遇时就都到达了终点
询问次数\(q=2*t+2*x+t=2*x+3*t<3*(x+t)\),故可以通过此题
#include<bits/stdc++.h>
using namespace std;
#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define fo(i,a) for(int i=0;i<a;++i)
#define il inline
string s;
il int read(){
int x;scanf("%d",&x);
go(i,1,x) cin>>s;
return x;
}
int main(){
//freopen("input.txt","r",stdin);
while(23333){
puts("next 0 1");
cout.flush();
read();
puts("next 0");
cout.flush();
if(read()==2) break;
}
while(23333){
puts("next 2 3 0 1 4 5 6 7 8 9");
cout.flush();
if(read()==1) break;
}
puts("done");
cout.flush();
return 0;
}