QOJ.ac

QOJ

Type: Editorial

Status: Open

Posted by: jiangly

Posted at: 2025-12-13 00:43:51

Last updated: 2025-12-13 00:44:02

Back to Problem

题解

题意

给定数列 $[a_1,a_2,\ldots]$,其递归定义为:$a_1=1$, $a_2=2$, $a_{2n+1}=2a_{2n}$, $a_{2n+2}=a_{2n+1}+r_n$,其中 $n\ge 1$,$r_n$ 是最小的不能表示为 $a_1,a_2,\ldots,a_{2n+1}$ 中两项的差的正整数。可以证明,任意一个正整数都能唯一的表示为数列 $a$ 中两项的差 $a_p-a_q$。给定 $n$ ($1\le n\le 10^5$) 个正整数 $x$ ($1\le x\le 10^9$),求出这个表示。

题解

由于 $a_{56}=1062283805$, $a_{57}=2a_{56}$,在这之后所有不超过 $10^9$ 的差都是 $a_{2n+2}-a_{2n+1}$ 的形式。那么求出所有 $1\le q< p\le 56$ 的答案,所有不在这些当中的数会以 $a_{58}-a_{57},a_{60}-a_{59},\ldots$ 的形式依次出现。因此每次询问二分即可。

代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
constexpr int A[] = {0, 1, 2, 4, 8, 16, 21, 42, 51, 102, 112, 224, 235, 470, 486, 972, 990, 1980, 2002, 4004, 4027, 8054, 8078, 16156, 16181, 32362, 32389, 64778, 64806, 129612, 129641, 259282, 259313, 518626, 518658, 1037316, 1037349, 2074698, 2074734, 4149468, 4149505, 8299010, 8299049, 16598098, 16598140, 33196280, 33196324, 66392648, 66392693, 132785386, 132785432, 265570864, 265570912, 531141824, 531141876, 1062283752, 1062283805};
std::vector<std::tuple<int, int, int>> ans;
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    for (int i = 1; i <= 56; ++i)
        for (int j = 1; j < i; ++j)
            if (A[i] - A[j] <= 1e9)
                ans.emplace_back(A[i] - A[j], i, j);
    std::sort(ans.begin(), ans.end());
    int t;
    std::cin >> t;
    while (t--) {
        int x;
        std::cin >> x;
        int k = std::lower_bound(ans.begin(), ans.end(), std::make_tuple(x + 1, 0, 0)) - ans.begin() - 1;
        auto [y, p, q] = ans[k];
        if (x != y) {
            p = 2 * (x - k + 27);
            q = p - 1;
        }
        std::cout << p << " " << q << "\n";
    }
    return 0;
}

Comments

No comments yet.