CF1019B The hat

一、题目

点此看题
在这里插入图片描述
谢谢恩泽的题面翻译,@Arextre

二、解法

首先 n n n 2 2 2的倍数但不为 4 4 4的倍数肯定是不行的,因为相对两个数隔了偶数个,所以奇偶性一定不同,所以两个数不同,可以在一开始的时候判掉。

i ′ i' i i i i的对应点, t i = a i − a i ′ t_i=a_i-a_{i'} ti=aiai,有一个性质,就是 t i + 1 − t i = ± 2   o r   0 t_{i+1}-t_i=\pm2\space or\space0 ti+1ti=±2 or 0,证明很简单,就是 t i + 1 t_{i+1} ti+1 t i t_i ti的差异只有两个格子的增减,所以只有这些情况。

可以考虑二分,设 l = 1 , r = n 2 l=1,r=\frac{n}{2} l=1,r=2n l , r l,r l,r算出来的 t t t一开始就异号,所以里面一定有解,我们假设分到 m i d mid mid,判断 m i d mid mid算出来的 t t t t l tl tl还是 t r tr tr异号,向那边继续分即可,中间算 t t t的时候就判断一下有没有算出 0 0 0,算出 0 0 0了就找到答案了。

讲完这个解法,相信你还有一些问题,比如为什么 l , r l,r l,r一开始就异号,我们把 t t t看作一个连续的函数,现在这段函数的定义域是 [ 1 , 2 n ] [1,\frac{2}{n}] [1,n2],发现 t n 2 + 1 t_{\frac{n}{2}+1} t2n+1 t n 2 t_{\frac{n}{2}} t2n差值一定是 ± 2   o r   0 \pm2\space or\space0 ±2 or 0,所以可以把定义域扩展到 [ 1 , n 2 + 1 ] [1,\frac{n}{2}+1] [1,2n+1]然后 1 1 1 n 2 + 1 \frac{n}{2}+1 2n+1一定异号(你看定义呀!),所以 l , r l,r l,r一开始就异号。

真是道神题,贴个代码吧qwq。

#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
int read()
{
 int x=0,flag=1;char c;
 while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
 while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
 return x*flag;
}
int n;
int ask(int x)
{
    cout<<"? "<<x<<endl;int a=read();
    cout<<"? "<<x+n/2<<endl;int b=read();
    if(a==b)
    {
        cout<<"! "<<x<<endl;
        exit(0);
    }
    return a-b;
}
int main()
{
    n=read();
    if(n%4) {printf("! -1\n");return 0;}
    int l=1,r=n>>1,tl=ask(l),tr=ask(r);
    while(l<=r)
    {
        int mid=(l+r)>>1,tm=ask(mid);
        if(tl*tm<0) r=mid-1,tr=tm;
        else l=mid+1,tl=tm;
    }
    cout<<"! -1"<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值