CF1114E Arithmetic Progression(交互题,二分,随机算法)
既然是在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(交互题,二分,随机算法)的更多相关文章
- Codeforces Round #371 (Div. 2) D. Searching Rectangles 交互题 二分
D. Searching Rectangles 题目连接: http://codeforces.com/contest/714/problem/D Description Filya just lea ...
- CF1370F2-The Hidden Pair(Hard Version)【交互题,二分】
正题 题目链接:https://www.luogu.com.cn/problem/CF1370F2 题目大意 \(T\)组数据,给出\(n\)个点的一棵树,有两个隐藏的关键点.你每次可以询问一个点集, ...
- CF1114E Arithmetic Progression
给定一个打乱的等差数列,每次两种操作. 1.查询一个位置. 2.查询是否有比x大的数字. 一共60次操作. sol: 30次操作即可二分出首项. 剩下30次操作查询出30个位置然后两两做差取gcd即可 ...
- Codeforces 1114E - Arithmetic Progression - [二分+随机数]
题目链接:http://codeforces.com/problemset/problem/1114/E 题意: 交互题,有一个 $n$ 个整数的打乱顺序后的等差数列 $a[1 \sim n]$,保证 ...
- Subway Pursuit (二分)(交互题)
题目来源:codeforces1039B Subway Pursuit 题目大意: 在1到n里有一个运动的点,要求找到这个点,每次可以查询一个区间内有没有这个点,每次这个点往左或者往右移动1到k个位置 ...
- Codeforces Round #499 (Div. 2) D. Rocket_交互题_二分
第一次作交互题,有点不习惯. 由于序列是循环的,我们可以将一半的机会用于判断当前是否是在说谎,另一半的机会用于二分的判断. 对于判断是否实在说谎,用1判断即可.因为不可能有比1还小的数. 本题虽然非常 ...
- 【Warrior刷题笔记】力扣169. 多数元素 【排序 || 哈希 || 随机算法 || 摩尔投票法】详细注释 不断优化 极致压榨
题目 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/majority-element/ 注意,该题在LC中被标注为easy,所以我们更多应该关 ...
- CF 1114 E. Arithmetic Progression
E. Arithmetic Progression 链接 题意: 交互题. 有一个等差序列,现已打乱顺序,最多询问60次来确定首项和公差.每次可以询问是否有严格大于x的数,和查看一个位置的数. 分析: ...
- 随机算法 - HNU 13348 Finding Lines
Finding Lines Problem's Link: http://acm.hnu.cn/online/?action=problem&type=show&id=13348&am ...
随机推荐
- SJP's Blog
This is SJP's blog. Here is a mirror web of his blog.
- springboot 发送邮件+模板+附件
package com.example.demo; import org.junit.Test;import org.junit.runner.RunWith;import org.springfra ...
- 【JVM.8】类加载及执行子系统的案例与实战
一. 案例分析 1. Tomcat:正统的类加载器架构 主流的Java Web服务器,如Tomcat.Jetty.WebLogic.WebSphere或其他服务器,都实现了自己定义的类加载器(一般都不 ...
- .net mvc数据库操作添加数据的几中方法
1. Defining sets on a derived context 1) DbSet属性:指定集合为Entity类型 2) IDbSet属性 3) 只读set属性 public IDbSet& ...
- CentOS 6下gcc升级的操作记录(由默认的4.4.7升级到6.4.0版本)
机房一台centos6.9机器部署了jenkins发布系统,开发人员在用node编译js,发现依赖的gcc版本低了,故需要将gcc升级到高版本(至少5.0版本以上),这里选择升级到6.4.0版本,下面 ...
- Ceph分布式存储-运维操作笔记
一.Ceph简单介绍1)OSDs: Ceph的OSD守护进程(OSD)存储数据,处理数据复制,恢复,回填,重新调整,并通过检查其它Ceph OSD守护程序作为一个心跳 向Ceph的监视器报告一些检测信 ...
- 【2016.3.22】作业 Word count 小程序
今天更下word count程序的设计思路及实现方法. 我的程序贴在coding里,这里就先不贴出来了, 我的coding地址:https://coding.net/u/holy_angel/p/wo ...
- 基于SSH框架开发的《高校大学生选课系统》的质量属性的实现
基于SSH框架开发的<高校大学生选课系统>的质量属性的实现 对于可用性采取的是错误预防战术,即阻止错误演变为故障:在本系统主要体现在以下两个方面:(1)对于学生登录模块,由于初次登陆,学生 ...
- netsh 转发 5000 端口到 80端口的命令和删除方法
归集整理一下 netsh 的几个简单命令. 实现端口转发等作用. 注意 命令. netsh connectaddress= listenaddress 的地址 目的 是 对外服务的 target 的 ...
- [转帖]浅析java程序的执行过程
浅析java程序的执行过程 转帖来源: https://www.cnblogs.com/wangjiming/p/10315983.html 之前学习过 这一块东西 但是感觉理解的不深刻. copy一 ...