CF2109C1 Hacking Numbers (Easy Version) 解题报告
题目传送门
题目大意
交互题。
add y表示将x 增加y(-10^{18}\le y\le 10^{18}) ;mul y表示将x 乘上y(1\le y\le 10^{18}) ;div y表示将x 除以y(1\le y\le 10^{18}) ;digit表示将x 的十进制各位数字相加,赋值给x ;
在以上的四种操作中,如果假设
在确定 ! 结束这组数据,这时交互机会返回一个值
解题思路
一种思路为可以将
那么如何去选取这个确定的数呢?最容易想到的这个确定的数就是 digit、add 和 div 三种操作。由于 div 操作必须是整除这次操作才有效,所以我们这里不考虑 div 操作。
- 第一次缩小:显而易见
digit操作可以将这个范围缩小到更小,于是:1\le x\le 10^9\to1\le x\le81(x=10^9-1\ 时取到\ 81) ; - 第二次缩小:这里再用一次
digit操作可以将范围继续缩小,于是:1\le x\le 81\to1\le x\le16(x=79\ 时取到\ 16) ; - 第三次缩小:注意这里如果再用一次
digit操作最多最多将x 缩小到1\le x\le 9 ,而运用add操作每次可以将范围折半,即add y这里y 取\left \lceil \frac{x}{2} \right \rceil ,这样我们就可以用add -8操作得到:1\le x\le 16\to1\le x\le8 ; - 同理可得第四次缩小
add -4得到1\le x\le 8\to1\le x\le4 ; - 第五次缩小
add -2得到1\le x\le 4\to1\le x\le2 ; - 第六次缩小
add -1得到1\le x\le 2\to x=1 ;
六次结束,这里 mul n 和 add n-1 两种操作得到 TLE 的好成绩,原因是当 add 0,所以避免特判,我选择了前者。
单次时间复杂度
不要忘记每次输出后清空缓存区哦。
AC Code
这里只放主函数。
signed main()
{
int T=re();
while(T--)
{
int n=re();
int ci=2;
while(ci--)
{
puts("digit");
cout.flush();
int op=re();
}
puts("add -8");
cout.flush();
int op=re();
puts("add -4");
cout.flush();
op=re();
puts("add -2");
cout.flush();
op=re();
puts("add -1");
cout.flush();
op=re();
printf("mul %d\n",n);
cout.flush();
op=re();
puts("!");
cout.flush();
op=re();
}
return 0;
}