【题目链接】
【思路要点】
- 这个数列是指数级增长的,小于\(10^9\)的项数只有\(O(Log10^9)\)。
- 当这个数列的某一项达到\(10^9\)后,相差在\(10^9\)以内的两项就只有可能是相邻的偶项和奇项。
- 因此,暴力计算数列在\(10^9\)内的项,并记录两两之差,在询问时二分即可。
- 时间复杂度\(O(Log^210^9+QLogLog10^9)\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 100005; const int INF = 1e9 + 5; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct info {int x, p, q; }; bool operator < (info a, info b) {return a.x < b.x; } info a[MAXN]; int n, val[MAXN]; int tot, delta[MAXN]; int mex() { int ans = 1; while (a[ans].x == ans) ans++; return ans; } int main() { val[1] = 1, val[2] = 2; a[tot = 1] = (info) {1, 2, 1}; for (int i = 3; val[i - 1] <= INF; i += 2) { val[i] = val[i - 1] * 2; for (int j = 1; j <= i - 1; j++) a[++tot] = (info) {val[i] - val[j], i, j}; sort(a + 1, a + tot + 1); val[i + 1] = val[i] + mex(); for (int j = 1; j <= i; j++) a[++tot] = (info) {val[i + 1] - val[j], i + 1, j}; sort(a + 1, a + tot + 1); n = i + 1; } for (int i = 1; i <= tot; i++) delta[i] = a[i].x; int q; read(q); while (q--) { int x; read(x); int tmp = lower_bound(delta + 1, delta + tot + 1, x) - delta; if (delta[tmp] == x) printf("%d %d\n", a[tmp].p, a[tmp].q); else { tmp = x - (tmp - 1); printf("%d %d\n", n + tmp * 2, n + tmp * 2 - 1); } } return 0; }