简单交互题选讲&交互题浅谈

一些定义与技巧

交互题,顾名思义,你需要用电脑与官方机器交流,从而得出一些东西。这一类题目,往往限制你交流(或询问)的次数,让你猜出一个东西来。

这是一类十分新颖的题,下面有几个比较经典的技巧:
①二分/三分
②巧用随机数

事实上,这一种题目与传统型题也并没有差多少,还是考验数学能力,甚至图论能力等。比赛中遇到了,往往难度不会小,甚至出现全场爆 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 Ain),每次你可以查询两个数的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)(n1,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 (n1)+1=n

②没有相同的数
显然,此时的这些数是一个以 0 0 0为下标的排列。
我们该怎么办呢?巧妙运用 n n n 2 2 2的次方数的特点,可以发现两个性质:
①存在两个数,分别是 0 0 0 2 n − 1 2^{n-1} 2n1(即 0000...00 0000...00 0000...00 1000...00 1000...00 1000...00),从而可以确定出除最高位外的其他数位。
②存在两个数 n − 2 n-2 n2 n − 1 n-1 n1,它们的第 k ( n = 2 k ) k(n=2^k) k(n=2k)位上(即最高位)的数相同,从而可以确定出最高位。

询问次数 ( n − 1 ) + 2 = n + 1 (n-1)+2=n+1 (n1)+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!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值