CF1114E Arithmetic Progression 随机化+二分+交互

一共有 60 次询问机会,显然可以用 30 次来确定序列的最大值(二分)

然后再用 30 次随机获得 30 个位置的值,那么有 $a_{j}=a_{i}+k\times 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\n",mid),++cnt,fflush(stdout);      
		scanf("%d",&x);              
		if(!x) ans=mid,r=mid-1; 
		else l=mid+1;     
	}     
	if(n==1) { printf("! %d %d\n",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\n",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\n",ans-(n-1)*les,les);    
	return 0;  
}

  

posted @ 2020-06-09 14:01  EM-LGH  阅读(157)  评论(0编辑  收藏  举报