一共有 60 次询问机会,显然可以用 30 次来确定序列的最大值(二分)
然后再用 30 次随机获得 30 个位置的值,那么有 $a_{j}=a_{i}+k imes d$,($d$ 为公差)
那么 $d$ = $gcd(d1,d2,d3,....dn)$,故将 30 个数排序,然后求一下两两之间差值的 $gcd$ 即可.
code:
#include <bits/stdc++.h> #define N 1000009 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int perm[N],vis[N],bu[N]; int get(int X) { return (rand()<<15|rand())%X+1; } int main() { srand(19260817); // setIO("input"); int n,l=0,r=1e9,mid,ans=0,cnt=0,x,y,z,g=0; scanf("%d",&n); while(l<=r) { mid=(l+r)>>1; printf("> %d ",mid),++cnt,fflush(stdout); scanf("%d",&x); if(!x) ans=mid,r=mid-1; else l=mid+1; } if(n==1) { printf("! %d %d ",ans,0),fflush(stdout); return 0; } for(int i=1;i<=60-cnt;++i) { int gc=0; do { x=get(n),++gc; } while(vis[x]&&gc<=9); if(gc>9) continue; vis[x]=1; printf("? %d ",x),fflush(stdout); ++g,scanf("%d",&bu[g]); } sort(bu+1,bu+1+g); int les=bu[2]-bu[1]; for(int i=2;i<g;++i) les=__gcd(les,bu[i+1]-bu[i]); printf("! %d %d ",ans-(n-1)*les,les); return 0; }