文章目录
一些定义与技巧
交互题,顾名思义,你需要用电脑与官方机器交流,从而得出一些东西。这一类题目,往往限制你交流(或询问)的次数,让你猜出一个东西来。
这是一类十分新颖的题,下面有几个比较经典的技巧:
①二分/三分
②巧用随机数
事实上,这一种题目与传统型题也并没有差多少,还是考验数学能力,甚至图论能力等。比赛中遇到了,往往难度不会小,甚至出现全场爆 0 0 0的惨状。
一些例题
例1. [CF1167B]Lost Numbers
Description
有一个由4 8 15 16 23 42组成的排列,你可以询问任意两个下标上的数的乘积,试着找到并输出这个排列。
最多询问4次。
Solution
一道交互的入门题,但是如果你是第一次做交互题,那你会很难一遍 A C AC AC。
先说思路: 我们询问 ( 1 , 2 ) ( 2 , 3 ) ( 3 , 4 ) ( 4 , 5 ) (1,2)(2,3)(3,4)(4,5) (1,2)(2,3)(3,4)(4,5),就可以得出第 1 , 2 , 3 , 4 , 5 1,2,3,4,5 1,2,3,4,5个位置是什么数,从而第 6 6 6个位置就能确定下来。
然后说一说注意事项。请打起精神,这一块特别重要:
(1)请注意格式
输出前一定要加上
!
!
!与一个空格,还有输入格式也要注意。
(2)每输出一次(即询问一次),就要写下面一行代码:
fflush(stdout);
如果你不是C++语言选手,你就要这么写,比如
Java:
system.out.flush()
Python:
stdout.flush()
Pascal:
flush(output)
例2. [CF1407C]Chocalate Bunny
Description
存在一个长度为 n n n的排列( n n n给定),每次你可以查询 a x m o d a y a_x \mod\ a_y axmod ay( x , y x,y x,y给定);最后确定整个排列。
询问次数最多为 2 n 2n 2n次。
Solution
首先,如果只有两个数,我们该怎么办?
假设这两个数是 x , y x,y x,y,我们有了 x m o d y x \mod y xmody与 y m o d x y \mod\ x ymod x,该如何求出 x , y x,y x,y呢?假设 x m o d y = a x \mod y=a xmody=a, y m o d x = b y \mod\ x=b ymod x=b。可以发现,一个数模比它大的数是它本身,而比它大的数模它却比它本身小。所以,如果 x > y x>y x>y,那么 a = x a=x a=x;否则 b = y b=y b=y。
所以,我们通过两次询问,就能求出两个数中较小的那个数的值。
由于只有 2 n 2n 2n次询问,我们直接双指针扫一遍即可。更具体地说,如果这个数被确定了,那么这个数对应的指针就向右移;这样两个指针移动的方向就是单调向右的,不会超过 2 n 2n 2n次询问。
当然,我们也可以两重循环,如果 i , j i,j i,j中有一个或两个被确定了,那么就continue;这样就能确定出每一个位置的值,询问次数也有保障。
例3. [CF1451E2]Bitwise Queries
Description
存在一个长度为 n ( n = 2 k ) n(n=2^k) n(n=2k)的序列A( n n n给定, k k k为自然数, A i < n A_i<n Ai<n),每次你可以查询两个数的xor(按位异或)或or(按位或)或and(按位与)。
请通过不超过 n + 1 n+1 n+1次询问求出整个排列。
Solution
首先,我们求出 ( 1 , 2 ) ( 2 , 3 ) … … ( n − 1 , n ) (1,2)(2,3)……(n-1,n) (1,2)(2,3)……(n−1,n)的异或。这样,我们就能求出任意两个数的任意两位是否相同。
分类讨论:
①有相同的数
假设这两个相同的数对应的位置是
(
u
,
v
)
(u,v)
(u,v),我们只需要查询
(
u
,
v
)
(u,v)
(u,v)的与即可;从而确定出
(
u
,
v
)
(u,v)
(u,v)每一位的值,从而确定出整个序列。
询问次数 ( n − 1 ) + 1 = n (n-1)+1=n (n−1)+1=n
②没有相同的数
显然,此时的这些数是一个以
0
0
0为下标的排列。
我们该怎么办呢?巧妙运用
n
n
n是
2
2
2的次方数的特点,可以发现两个性质:
①存在两个数,分别是
0
0
0与
2
n
−
1
2^{n-1}
2n−1(即
0000...00
0000...00
0000...00与
1000...00
1000...00
1000...00),从而可以确定出除最高位外的其他数位。
②存在两个数
n
−
2
n-2
n−2与
n
−
1
n-1
n−1,它们的第
k
(
n
=
2
k
)
k(n=2^k)
k(n=2k)位上(即最高位)的数相同,从而可以确定出最高位。
询问次数 ( n − 1 ) + 2 = n + 1 (n-1)+2=n+1 (n−1)+2=n+1。
此时所有数位都被确定,那么整个序列就都被确定了。
Summary
巧妙运用了本题的多个条件,结合位运算的一些基本性质,我们解决了本题。
例4. [CF1114E]Arithmetic Progression
Description
Solution
可以发现,如果我们确定了末项与公差,那么首项就能求出来。
那么如何求出末项呢?很简单,我们直接二分这个末项,每次询问(第二种)即可确定。但是公差似乎很难搞的样子……
⌊ \lfloor ⌊ 考虑随机数算法 ⌉ \rceil ⌉
我们用完所有的 60 60 60次询问(接下来的询问均为第一种),尽可能多求出一些在序列中出现过的数。然后,将这些数排序,公差就是这个序列的差分数组的最大公约数。
最后,注意 r a n d rand rand函数的值域在 W i n d o w s Windows Windows下很小,要通过一些技巧使其值域扩大,可以自己乱搞。另外,在 C F CF CF里面千万不要使用 s r a n d ( t i m e ( 0 ) ) srand(time(0)) srand(time(0)),这会让你 W A WA WA,因为在CF中这是一个定值。
Summary
巧妙运用了等差数列的性质,得到了一个随机数算法,是一道套路题。
sto 随机数算法 orz!