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; }