博客
关于我
The hat
阅读量:314 次
发布时间:2019-03-04

本文共 2157 字,大约阅读时间需要 7 分钟。

题目

题目概要
对于数列 a 1 , a 2 , a 3 , … , a n a_1,a_2,a_3,\dots,a_n a1,a2,a3,,an ,满足相邻两项的差为一,且最后一项与第一项差为一。

任求一个 x x x 使得 a x = a x + n 2 a_x=a_{x+\frac{n}{2}} ax=ax+2n 。你有 60 60 60 次机会询问 a a a 数列中某一项的值。

数据范围与约定
n ≤ 1 0 5 n\le 10^5 n105 n n n 将于输入中给出。

思路

我们因地制宜,令 f ( x ) = a x − a x + n 2 f(x)=a_x-a_{x+\frac{n}{2}} f(x)=axax+2n

问题为求其零点。

不妨令 a x = a x − n ( n < x ) a_x=a_{x-n}(n<x) ax=axn(n<x) ,即将 a a a 数列重复无数次。

不难发现,现在的 a a a 数列仍然满足 a x − a x − 1 ∈ { − 1 , 1 } a_x-a_{x-1}\in\{-1,1\} axax1{ 1,1} (本质是破环成链,复制了一次)。

此时, f ( x ) − f ( x − 1 ) = ( a x − a x − 1 ) − ( a x + n 2 − a x − 1 + n 2 ) f(x)-f(x-1)=(a_x-a_{x-1})-(a_{x+\frac{n}{2}}-a_{x-1+\frac{n}{2}}) f(x)f(x1)=(axax1)(ax+2nax1+2n) ,因为两者都是 { − 1 , 1 } \{-1,1\} { 1,1} 中的一个值,所以

f ( x ) − f ( x − 1 ) ∈ { + 2 , 0 , − 2 } f(x)-f(x-1)\in\{+2,0,-2\} f(x)f(x1){ +2,0,2}

那么,可以看出,如果说将纵轴压缩一下,原本的 ( x , y ) (x,y) (x,y) 压缩到 ( x , y 2 ) (x,\frac{y}{2}) (x,2y) ,那么 f ( x ) f(x) f(x) 是“连续”的。

由定义,我们还发现 f ( 1 ) + f ( n 2 + 1 ) = 0 f(1)+f\left(\frac{n}{2}+1\right)=0 f(1)+f(2n+1)=0

也就是说, f ( 1 ) f(1) f(1) f ( n 2 + 1 ) f(\frac{n}{2}+1) f(2n+1) 异号

异号,且连续,求零点,众所周知,用 二分法即可

代码

#include <cstdio>#include <iostream>#include <vector>#include <algorithm>using namespace std;inline int readint(){   	int a = 0; char c = getchar(), f = 1;	for(; c<'0' or c>'9'; c=getchar())		if(c == '-') f = -f;	for(; '0'<=c and c<='9'; c=getchar())		a = (a<<3)+(a<<1)+(c^48);	return a*f;}inline void writeint(int x){   	if(x > 9) writeint(x/10);	putchar((x%10)^48);}# define MB template < class T >MB void getMax(T &a,const T &b){    if(a < b) a = b; }MB void getMin(T &a,const T &b){    if(b < a) a = b; }int query(int x){   	printf("? %d\n",x);	fflush(stdout);	return readint();}# define f(x) (query(x)-query(x+(n>>1)))# define guess(x) { printf("! %d\n",x); return 0; }int main(){   	int n = readint(); // 难得的没有压行	int l = 1, lval = f(l), r = (n>>1), rval = f(r);	if(lval%2 != 0) guess(-1); // impossible	if(lval == 0) guess(l); if(rval == 0) guess(r);	while(true){    // 范围是(l,r)		int mid = (l+r)>>1, d = f(mid); if(d == 0) guess(mid);		if((d > 0) != (lval > 0)) r = mid; else l = mid;	} // 一定会运行一次GUESS的	return 0;}

转载地址:http://hhvq.baihongyu.com/

你可能感兴趣的文章
在线工作坊 | 机器学习之朴素贝叶斯算法 - 原来如此通俗易懂
查看>>
《进击吧!Blazor!》第一章 4.数据交互
查看>>
不下载直接使用JQuery和Bootstrap的方法
查看>>
Spring的IOC注入(入门介绍)
查看>>
分享一个500异常
查看>>
怎么玩LOG4J
查看>>
Oracle创建用户,分配表空间
查看>>
自定义标签(JSP2.0)简单标签
查看>>
MyBatis自定义类型转换器
查看>>
SpringBoot缓存入门篇
查看>>
Nacos的安装和运行
查看>>
机器学习(湖北师范大学教程)-极大似然估计算法
查看>>
2019年下半年总结
查看>>
Java基础
查看>>
读《红楼梦》有感
查看>>
Java如何模拟现实世界(1)-类、对象
查看>>
redis双击redis-server.exe,然后会发现闪退
查看>>
【数据库视频之数据库视图】
查看>>
【数据库视频之数据库规则、约束】
查看>>
【数据库视频之操作查询(一)】
查看>>