【交互】CF1081F Tricky Interactor

【题目】
原题地址
有一个长度为 n n n 01 01 01串,初始告诉你串中 1 1 1的个数,你可以进行不超过 1 0 4 10^4 104次操作,每次操作形如 ( l , r ) (l,r) (l,r),将会随机使区间 [ 1 , r ] [1,r] [1,r] [ l , n ] [l,n] [l,n]其中一段全部取反,并返回现在串中 1 1 1的个数,求原串。 n ≤ 300 n\leq 300 n300

【解题思路】
首先我们知道一个结论:翻转一个区间,则这个全局中 [ 1 个 数 的 变 化 量 ] ≡ [ 区 间 长 度 ] ( mod  2 ) [1个数的变化量]\equiv [区间长度](\text{mod}\ 2) [1][](mod 2)

  • 设一次翻转区间 [ l , r ] [l,r] [l,r],全局 1 1 1的个数从 x x x变成 y y y,这个区间内原来有 t t t 1 1 1 y − x = ( r − l + 1 ) − 2 t y-x=(r-l+1)-2t yx=(rl+1)2t

所以我们如果让 [ 1 , l ] [1,l] [1,l] [ r , n ] [r,n] [r,n]的长度不同,我们就可以知道翻转的是哪一个区间,我们也就知道了。

现在还要解决的问题是怎么样使得这个串翻转我们期望翻转的一段。实际上我们如果想单独翻转 [ 1 , l ] [1,l] [1,l]这一段,我们只需要一直对 [ l , r ] [l,r] [l,r]操作即可,期望操作次数应该是 3 3 3次,具体证明的话也不难:

  • 我们令 f 0 / 1 , 0 / 1 f_{0/1,0/1} f0/1,0/1表示每一段翻不翻转时期望多少步能翻转到 f 1 , 0 f_{1,0} f1,0,我们可以列出等式: f 0 , 0 = f 0 , 1 + f 1 , 0 2 + 1 , f 0 , 1 = f 0 , 0 + f 1 , 1 2 + 1 , f 1 , 1 = f 1 , 0 + f 0 , 1 2 + 1 f_{0,0}=\frac {f_{0,1}+f_{1,0}} 2+1,f_{0,1}=\frac {f_{0,0}+f_{1,1}} 2+1,f_{1,1}=\frac {f_{1,0}+f_{0,1}} 2+1 f0,0=2f0,1+f1,0+1,f0,1=2f0,0+f1,1+1,f1,1=2f1,0+f0,1+1. 那么 f 0 , 0 = 3 , f 0 , 1 = 4 , f 1 , 1 = 3 f_{0,0}=3,f_{0,1}=4,f_{1,1}=3 f0,0=3,f0,1=4,f1,1=3

综上,我们可以得到下面这个做法:我们设 s i s_i si表示第 i i i位的数字。

  • n n n是奇数,我们每次应当询问一个长度为偶数的区间,于是我们可以查询 ( 2 , n ) , ( 1 , 2 ) , ( 2 , 3 ) , ( 3 , 4 ) … ( n − 2 , n − 1 ) (2,n),(1,2),(2,3),(3,4)\dots (n-2,n-1) (2,n),(1,2),(2,3),(3,4)(n2,n1),目的是为了翻转 [ 2 , n ] , [ 1 , 2 ] , [ 1 , 3 ] … [ 1 , n − 1 ] [2,n],[1,2],[1,3]\dots[1,n-1] [2,n],[1,2],[1,3][1,n1],这样我们可以知道 s 1 + s 2 , s 1 + s 2 + s 3 , … s_1+s_2,s_1+s_2+s_3,\dots s1+s2,s1+s2+s3,以及 s 2 + s 3 + ⋯ + s n s_2+s3+\dots+s_n s2+s3++sn于是 s s s就唯一确定了。
  • n n n是偶数,我们每次应当询问一个长度为奇数的区间,于是我们可以查询 ( 1 , 1 ) , ( 2 , 2 ) , ( 3 , 3 ) … ( n − 1 , n − 1 ) (1,1),(2,2),(3,3)\dots (n-1,n-1) (1,1),(2,2),(3,3)(n1,n1),目的是为了翻转 [ 1 , 1 ] , [ 1 , 2 ] , [ 1 , 3 ] … [ 1 , n − 1 ] [1,1],[1,2],[1,3]\dots[1,n-1] [1,1],[1,2],[1,3][1,n1],这我们可以知道 s 1 , s 1 + s 2 , s 1 + s 2 + s 3 , … s_1,s_1+s_2,s_1+s_2+s_3,\dots s1,s1+s2,s1+s2+s3,同样可以得到答案。

【参考代码】

#include<bits/stdc++.h>
#define fi first
#define se second
#define mkp make_pair
#define pb push_back
using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N=1e4+10;
int n,cnt,a[N],ans[N];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

bool flip(int l,int r)
{
	printf("? %d %d\n",l,r);fflush(stdout);
	a[++cnt]=read();return (a[cnt]-a[cnt-1])&1;
}

int main()
{
	n=read();ans[n]=a[0]=read();
	for(int i=1;i<n;++i)
	{
		int x=a[cnt],t[2]={0,0};
		if(i==1 && n&1)
		{
			while(!t[0] || t[1]) t[flip(2,n)]^=1;
			int y=a[cnt];
			ans[i]=ans[n]-(n-1-y+x)/2;
			while(t[0] || t[1]) t[flip(2,n)]^=1;
		}
		else
		{
			while(!t[0] || t[1]) t[(flip(i-(n&1),i)^i)&1]^=1;
			int y=a[cnt];
			ans[i]=(i-y+x)/2;
			while(t[0] || t[1]) t[(flip(i-(n&1),i)^i)&1]^=1;
		}
	}
	printf("! ");
	for(int i=1;i<=n;++i) printf("%d",ans[i]-ans[i-1]);
	puts("");fflush(stdout);

	return 0;
}

【总结】
一道十分有趣的交互题。
集训队出题就是不一样。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值