CF 1114 E. Arithmetic Progression

E. Arithmetic Progression

链接

题意:

  交互题。

  有一个等差序列,现已打乱顺序,最多询问60次来确定首项和公差。每次可以询问是否有严格大于x的数,和查看一个位置的数。

分析:

  首先可以二分找到序列的最大值,然后考虑如何求公差。

  随机选30个数,然后对任意两个求一遍gcd即可。

  正确性证明

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;


inline int query(int ty,LL x) {
    int y;
    if (ty == 1) printf("> %I64d\n", x);
    else printf("? %I64d\n", x);
    fflush(stdout);
    cin >> y;
    if (y == -1) exit(0);
    return y;
}

vector<LL> vec;
int Rand() { return (rand() << 15) | rand(); }
int id[1000005];

int main() {
    srand(1114);
    int n; cin >> n;
    LL l = -1e9, r = 1e9, ans = 0, cnt = 60, tot = n;
    while (l <= r) {
        LL mid = (l + r) >> 1;
        cnt --;
        if (query(1, mid) == 0) ans = mid, r = mid - 1;
        else l = mid + 1;
    }
    for (int i = 1; i <= tot; ++i) id[i] = i;
    while (cnt > 0 && tot > 0) {
        int x = Rand() % tot + 1;
        vec.push_back(query(0, id[x]));
        swap(id[x], id[tot]);
        tot --;    cnt --;    
    }
    sort(vec.begin(), vec.end());
    if (vec.back() != ans) vec.push_back(ans);
    LL d = vec[1] - vec[0];
    for (int i = 0; i < (int)vec.size() - 1; ++i) d = __gcd(d, vec[i + 1] - vec[i]);
    printf("! %I64d %I64d\n", ans - (n - 1) * d, d);
    return 0;
}

 

posted @ 2019-02-11 11:37  MJT12044  阅读(377)  评论(0编辑  收藏  举报