既然是在CF上AC的第一道交互题,而且正是这场比赛让我升紫了,所以十分值得纪念。

题目链接:CF原网

题目大意:交互题。

有一个长度为 $n$ 的序列 $a$,保证它从小到大排序后是个等差数列。你不知道这个序列长什么样,但你可以询问:

  • $?\ i$ 表示询问 $a_i$ 的值;
  • $>\ x$ 表示询问序列中是否存在严格大于 $x$ 的数。

你可以问不超过 $60$ 个询问。

现在,你需要求出这个等差数列的首项(也就是 $a$ 中的最小值)和这个等差数列的公差(也就是等差数列中相邻两个数的差)。

$2\le n\le 10^6,0\le a_i\le 10^9$。


看,第二个操作,明显暗示我们要二分最大值。(除了这个也没啥用了吧?)

用掉 $\log 10^9=30$ 个操作。

令 $mx$ 为我们二分出的最大值。

设公差为 $d$,那么 $\forall 1\le i\le n,d|(mx-a_i)$。

也就是如果我们知道的 $a_i$ 有 $x_1,x_2,x_3\dots,x_k$,那么 $d|\gcd(mx-x_1,mx-x_2,mx-x_3\dots,mx-x_k)$。

但这样就有一个严峻的问题:如果 $k$ 不够大,直接 $\gcd$ 得到的可能不是答案!

无路可走了,只有一个想法:随机!

我们随机 $30$ 个 $i$,询问这些 $a_i$ 的值。(为什么要随机呢?因为如果直接取前 $30$ 个 $a_i$ 很可能会被毒瘤卡掉)

$d$ 就是所有 $mx-a_i$ 的 $\gcd$ 了。

???这样不会错吗?

分析一下,我们设 $a_1=mx-k_1d,a_2=mx-k_2d\dots a_n=mx-k_nd$。那么我们求出的 $\gcd$ 就是随机出的 $30$ 个 $k_i$ 的 $\gcd$。

在 $10^6$ 中随机选 $30$ 个数,$\gcd$ 不为 $1$ 的概率就是出错的概率。

大致估算一下:

选出的 $k$ 都是 $2$ 的倍数的概率是 $\frac{1}{2^{30}}$。

选出的 $k$ 都是 $3$ 的倍数的概率是 $\frac{1}{3^{30}}$。

等等等等……

这样估算的话,出错概率是不会超过 $10^{-8}$ 的。

其实有更准确的求法,就是莫比乌斯反演,但由于我们只是来证明正确性的,就不讲了。

直接引用官方题解:

By some maths, we can find out the probability of our solution to fail being relatively small — approximately $1.86185\times 10^{-9}$.

直接上rand()就做完了……

了吗?

对了,这就是出题人恶毒所在了……

rand()和random_shuffle()的上界都是32767,访问不到后面大部分的元素。

于是出题人就把恶毒的数放在了前面……

那就用自己的rand()啊!写过treap吗?把那个rand搬过来就能用了!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int n,cnt,pt[maxn];
inline int rnd(){ //自己的rand
static int seed=;
return seed=(((seed*666666ll+)%)^)%;
}
int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
int main(){
n=read();
if(n<=){ //n<=60,随便玩
int mx=,mn=INT_MAX;
FOR(i,,n){
printf("? %d\n",i);
fflush(stdout);
int x=read();
mx=max(mx,x);
mn=min(mn,x);
}
printf("! %d %d\n",mn,(mx-mn)/(n-));
fflush(stdout);
return ;
}
int l=,r=1e9;
while(l<r){ //二分最大值
int mid=(l+r)>>;
printf("> %d\n",mid);
cnt++;
fflush(stdout);
int ver=read();
if(ver) l=mid+;
else r=mid;
}
int mx=r,ans=;
FOR(i,,n) pt[i]=i;
FOR(i,,n) swap(pt[i],pt[rnd()%n+]);
FOR(i,,min(n,-cnt)){ //随机60-cnt个元素
printf("? %d\n",pt[i]);
fflush(stdout);
int x=read();
ans=gcd(ans,mx-x); //取gcd
}
printf("! %d %d\n",mx-(n-)*ans,ans); //首项=末项-(项数-1)*公差
fflush(stdout);
}

CF1114E Arithmetic Progression(交互题,二分,随机算法)的更多相关文章

  1. Codeforces Round #371 (Div. 2) D. Searching Rectangles 交互题 二分

    D. Searching Rectangles 题目连接: http://codeforces.com/contest/714/problem/D Description Filya just lea ...

  2. CF1370F2-The Hidden Pair(Hard Version)【交互题,二分】

    正题 题目链接:https://www.luogu.com.cn/problem/CF1370F2 题目大意 \(T\)组数据,给出\(n\)个点的一棵树,有两个隐藏的关键点.你每次可以询问一个点集, ...

  3. CF1114E Arithmetic Progression

    给定一个打乱的等差数列,每次两种操作. 1.查询一个位置. 2.查询是否有比x大的数字. 一共60次操作. sol: 30次操作即可二分出首项. 剩下30次操作查询出30个位置然后两两做差取gcd即可 ...

  4. Codeforces 1114E - Arithmetic Progression - [二分+随机数]

    题目链接:http://codeforces.com/problemset/problem/1114/E 题意: 交互题,有一个 $n$ 个整数的打乱顺序后的等差数列 $a[1 \sim n]$,保证 ...

  5. Subway Pursuit (二分)(交互题)

    题目来源:codeforces1039B Subway Pursuit 题目大意: 在1到n里有一个运动的点,要求找到这个点,每次可以查询一个区间内有没有这个点,每次这个点往左或者往右移动1到k个位置 ...

  6. Codeforces Round #499 (Div. 2) D. Rocket_交互题_二分

    第一次作交互题,有点不习惯. 由于序列是循环的,我们可以将一半的机会用于判断当前是否是在说谎,另一半的机会用于二分的判断. 对于判断是否实在说谎,用1判断即可.因为不可能有比1还小的数. 本题虽然非常 ...

  7. 【Warrior刷题笔记】力扣169. 多数元素 【排序 || 哈希 || 随机算法 || 摩尔投票法】详细注释 不断优化 极致压榨

    题目 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/majority-element/ 注意,该题在LC中被标注为easy,所以我们更多应该关 ...

  8. CF 1114 E. Arithmetic Progression

    E. Arithmetic Progression 链接 题意: 交互题. 有一个等差序列,现已打乱顺序,最多询问60次来确定首项和公差.每次可以询问是否有严格大于x的数,和查看一个位置的数. 分析: ...

  9. 随机算法 - HNU 13348 Finding Lines

    Finding Lines Problem's Link: http://acm.hnu.cn/online/?action=problem&type=show&id=13348&am ...

随机推荐

  1. Web Audio介绍

    Web Audio还是一个比较新的JavaScript API,它和HTML5中的<audio>是不同的,简单来说,<audio>标签是为了能在网页中嵌入音频文件,和播放器一样 ...

  2. Wave - 花たん 音乐

    Wave 歌手:花たん 所属专辑:Flower 間違えて宇宙終わって(宇宙因为一个错误而终结了) 青信号はいつも通り(通行的灯号一如往常的) 飛んでまた止まって(又再停止传播) また 飛びそうだ(然后 ...

  3. 简易线程池Thread Pool

    1. 基本思路 写了个简易的线程池,基本的思路是: 有1个调度线程,负责维护WorkItem队列.管理线程(是否要增加工作线程).调度(把工作项赋给工作线程)等 线程数量随WorkItem的量动态调整 ...

  4. jq使用手册

    jq 使用手册   翻译整理:Young.J 官方网站:http://jquery.com    jQuery是一款同prototype一样优秀js开发库类,特别是对css和XPath的支持,使我们写 ...

  5. NodeJS学习:爬虫小探

    说明:本文在个人博客地址为edwardesire.com,欢迎前来品尝. 今天来学习alsotang的爬虫教程,跟着把CNode简单地爬一遍. 建立项目craelr-demo 我们首先建立一个Expr ...

  6. Xcode7 低版本iOS系统上下有黑边的问题

    在使用Xcode7开发时,默认的启动页改成了 Launch Screen storyboard.通常情况下还是习惯使用 LaunchImage,介绍下Xcode7 下如何改为启动页是LaunchIma ...

  7. 总结了关于PHP xss 和 SQL 注入的问题(转)

    漏洞无非这么几类,XSS.sql注入.命令执行.上传漏洞.本地包含.远程包含.权限绕过.信息泄露.cookie伪造.CSRF(跨站请求)等.这些漏洞不仅仅是针对PHP语言的,本文只是简单介绍PHP如何 ...

  8. 关于视频编辑SDK的接入说明

    一.运行环境 Android 4.1(api 16)以上: 处理器:双核 1GHz以上CPU(目前只支持ARM CPU, X86.MIPS暂不支持):推荐四核1.2GHz以上CPU 内存:1 GB以上 ...

  9. Threading.Timer用法

    protected System.Threading.Timer executeTimer;//定时器 private int interval;//定时器执行间隔周期 executeTimer = ...

  10. [转帖]Docker 清理占用的磁盘空间

    Docker(二十七)-Docker 清理占用的磁盘空间 https://www.cnblogs.com/zhuochong/p/10076599.html docker system docker ...