题面
Codeforces 1114E Arithmetic Progression 题目大意:给你一个打乱了顺序的等差数列,你有60次询问,每次可以询问每个位置的数是多少,或者可以询问有没有严格大于x的数。然后请你求出这个序列的最小值和公差。
解答
我对不起lyt老师,教了我等差数列,我还是不会。这道题,二分最大值+随机。先二分查找出最大的数,大约用去30次机会,在随机获取30个数,求个gcd,就可以求出公差了。这样错误的概率为$ 1.86185·10^{-9}.$(数据来源:官方题解)。毕竟这是我做的第一道交互题,不知道咋调试。太弱了。注意一下,rand函数要自己写一个,毕竟std里面的范围比较小,如果出题人比较毒瘤,把数据全部丢到那个范围以外,卡死我。 rand函数如下:
inline int rnd(){ //自己的rand
static int seed=19260817;//光速逃
return seed=(((seed*666666ll+20050818)%998244353)^1000000754)%10902060817;
}
# include <cstdio>
# include <algorithm>
# include <stdio.h>
# include <vector>
# include <iostream>
using namespace std;
const int MAXN = 100010;
using namespace std;
int asks = 0;
int getBigger(int x){
cout<<"> "<<x<<endl;
cout.flush();
int s;cin>>s;
return s;
}
int getVal(int pos){
cout<<"? "<<pos<<endl;
cout.flush();
int s;cin>>s;
return s;
}
inline int rnd(){ //自己的rand
static int seed=19260817;
return seed=(((seed*666666ll+20050818)%998244353)^1000000754)%10902060817;
}
int a[70];
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int main(){
int n;
cin>>n;
cout.flush();
int ans ;
int l = 0,r = (int)1e9+1;
while(l<=r){
int mid = l+r>>1;
asks++;
if(getBigger(mid))l = mid+1;
else r = mid-1,ans = mid;
}
int maxx = ans;
int d = 0;
for(int i = 1;i<=59-asks;i++)a[i] = getVal(rnd()%n+1);
for(int i = 1;i<=59-asks;i++){
for(int j = i+1;j<59-asks;j++)d = gcd(d,abs(a[i]-a[j]));
}
cout<<"! "<<maxx-d*(n-1)<<' '<<d;
return 0;
}