题目连接:http://codeforces.com/problemset/problem/1114/Eios
题意:c++
交互题,有一个 $n$ 个整数的打乱顺序后的等差数列 $a[1 \sim n]$,保证公差为正整数,你能够询问不超过 $60$ 次来找到该等差数列的首项和公差。spa
你能够作的询问有两种:code
一、询问是否存在某个数字大于 $x$。blog
二、询问序列中第 $i$ 个数是多少。ci
题解:get
首先能够用二分的方式找到这个等差数列的最大值,因为 $a[i] \in [0,1e9]$,因此最多 $30$ 次询问就能够找到这个最大值。博客
而后咱们能够用剩下的 $30$ 次询问随机查询一些位置,将这些数做差,求出全部差值的最大公因数,就是公差。it
另一个须要注意的点是https://codeforces.com/blog/entry/61587这篇博客中提到的,普通的rand()给出的随机数在 $[0,RAND\_MAX]$ 之间,可是只能保证 $RAND\_MAX$ 不小于 $32767$,所以在这个地方随机数的取值范围太小了,所以能够选用一些更好的随机数生成器 mt_rand 。io
AC代码:
#include<bits/stdc++.h> using namespace std; int n; map<int,bool> mp; int Find() { int l=0, r=1e9; while(l<r) { int mid=(l+r)/2; cout<<"> "<<mid<<endl; int x; cin>>x; if(x) l=mid+1; else r=mid; } return l; } int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin>>n; int mx=Find(); int d=0; mt19937 rnd(64708915); for(int i=1;i<=min(30,n);i++) { int idx; while(idx=rnd()%n+1) { if(mp.count(idx)) continue; mp[idx]=1; break; } cout<<"? "<<idx<<endl; int x; cin>>x; d=__gcd(d,mx-x); } cout<<"! "<<mx-(n-1)*d<<' '<<d<<endl; }