題目連接: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; }