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 ...
随机推荐
- Scala学习(六)练习
Scala中的对象&练习 1. 编写一个Conversions对象,加入inchesToCentimeters,gallonsToLiters和milesToKilometers方法 程序代码 ...
- SA的一个辣鸡trick
基础板子 namespace SA{ int x[400010],y[400010],SA[400010],rk[400010],ht[400010],t[400010]; int st[19][40 ...
- C#编写WINNT服务,随便解决安卓开发遇到的5037被众多程序无节操占用的问题
需求分析: 最近重新开始学习安卓开发,好久不用的ADT集成开发环境频繁遇到不能在仿真机和真机上调试的问题,也就是本人另一篇博文描述的ADB(Android Debug Bridge)监控的5037被金 ...
- 暴雪《争霸艾泽拉斯》*采用自适应 SSAO
在实时渲染过程中,屏幕空间环境光遮蔽 (SSAO) 常用于打造小范围环境光效果和接触阴影效果.它用于许多现代游戏,通常占用 5% 到 10% 的帧时间.在<争霸艾泽拉斯>* 游戏开发过程中 ...
- Jenkins日常运维笔记-重启数据覆盖问题、迁移、基于java代码发版(maven构建)
之前在公司机房部署了一套jenkins环境,现需要迁移至IDC机房服务器上,迁移过程中记录了一些细节:1)jenkins默认的主目录放在当前用户家目录路径下的.jenkins目录中.如jenkins使 ...
- ansible环境部署及常用模块总结 - 运维笔记
一. Ansible 介绍Ansible是一个配置管理系统configuration management system, python 语言是运维人员必须会的语言, ansible 是一个基于py ...
- android studio报Resolved versions for app (26.1.0) and test app (27.1.1)differ. 错误的解决办法
https://blog.csdn.net/qq_36636969/article/details/80278150
- Week 7 迭代总结
写在前面: 本次我为团队博客写了一篇总结,深刻总结了我们组发生的问题以及将来要做的事情.有兴趣请移步http://www.cnblogs.com/Buaa-software Week 7 Alpha轮 ...
- 《linux内核设计与分析》内核模块编程
内核模块编程 一.准备工作 虚拟机:VMware Workstation 12操作系统:ubuntu当前内核版本:linux-headers-4.4.0-22-generic 二.有关于内核模块的知识 ...
- 剑值offer:最小的k个数
这是在面试常遇到的topk问题. 题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 解题思路: 思路一:用快排对数 ...