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 ...
随机推荐
- linux下日志文件error监控报警脚本分享
即对日志文件中的error进行监控,当日志文件中出现error关键字时,即可报警!(grep -i error 不区分大小写进行搜索"error"关键字,但是会将包含error大小 ...
- Mysql抓包工具 - MySQL Sniffer 使用小结 (含带general_log日志)
在mysql运维工作中,一般会使用tcpdump做一些分析(直接读分析日志比较难以看明白,在数据库连接值高时使用):对于mysql实时的连接监控分析,通常会使用"mysqladmin/sho ...
- PHP从入门到精通(四)
PHP数组中的常用函数汇总 为了更直观的讲解各函数的作用和用法,方便大家的理解,首先,我们来定义一个数组.下面各函数的操作将以本数组为例: $arr = array(1,2,3,4,5,6," ...
- B. Vasya and Isolated Vertices
链接 [http://codeforces.com/contest/1065/problem/B] 题意 给你n个点,m条边,让你找最多孤立点和最少孤立点,不能有自环路 分析 对于最少max(0,n- ...
- 2016-03-22 OneZero团队 Daily Scrum Meeting
会议时间: 2016-03-22 9:33-9:57am 会议内容: 一.在原有Sprint Backlog基础上,我们加了亮点(摇一摇功能:随机选取一条记录在界面显示,以提醒主页君回忆) 需求分析图 ...
- 如何实现基于ssh框架的投票系统的的质量属性
如何实现基于ssh框架的投票系统的的质量属性: 项目 :网上考试系统 我做的是网上考试系统,因为标准化的考试越来越重要,而通过计算机进行标准化判卷,系统会自动判卷出成绩,组织考试的人不用组织人员打印试 ...
- C++中struct 和 class的区别
首先,C++中类的定义,从狭义上理解,就是我们使用的class类型.从广义上,类就是定义了一个新的类型和新的作用域,它具有成员函数和成员数据. 而对广义类定义的实现分为两种,一种是使用struct实现 ...
- Atcoder D - Knapsack 1 (背包)
D - Knapsack 1 Time Limit: 2 sec / Memory Limit: 1024 MB Score : 100100 points Problem Statement The ...
- 【转】STM32 独立看门狗简介
STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免这种 ...
- Apache+php安装和配置 windows
Apache+php安装和配置 windows Apache 安装 1.官网网址:http://httpd.apache.org/ 2.Download 3.点击链接Files for Microso ...