Codeforces - 1166D - Cute Sequences

地址

http://codeforces.com/contest/1166/problem/D

原文地址

https://www.lucien.ink/archives/433

题目

Given a positive integer $m$, we say that a sequence $x_1, x_2, \dots, x_n$ of positive integers is $m$-cute if for every index $i$ such that $2 \le i \le n$ it holds that $x_i = x_{i - 1} + x_{i - 2} + \dots + x_1 + r_i$ for some positive integer $r_i$ satisfying $1 \le r_i \le m$.

You will be given $q$ queries consisting of three positive integers $a$, $b$ and $m$. For each query you must determine whether or not there exists an $m$-cute sequence whose first term is $a$ and whose last term is $b$. If such a sequence exists, you must additionally find an example of it.

题意

定义 $x_i = x_{i - 1} + x_{i - 2} + \dots + x_1 + r_i$ ,$1 \le r_i \le m$ ,给你 a b m ,判断是否存在一个一个序列 $x$ ,假定这个序列的长度为 $n$ ,使得 $x_1 = a$ 且 $x_n = b$ 。

题解

规定 $2 ^ {x} = 0$ $(x < 0)$ ,归纳一下,可以发现:$$x_{n(n \ge 2)} = 2 ^ {n - 2}a + 2 ^ {n - 3} r_2 + 2 ^ {n - 4} r_3 + \dots + 2r_{n - 2} + r_{n - 1} + r_n\ \tag{a}$$

即判断是否存在一个 $x_n$ 满足 $(a)$ 式且 $x_n = b$ 。

可以进一步简写一下,如果将 $b$ 代入 $(a)$ 式,且令:$$r = 2 ^ {n - 3} r_2 + 2 ^ {n - 4} r_3 + \dots + 2r_{n - 2} + r_{n - 1} + r_n \tag{b}$$ 则有:$$b = 2 ^ {n - 2}a + r$$ 可以发现忽略 $(b)$ 式中的 $r_n$ 之后,剩下的式子为 $r$ 为一个二进制表示,我们可以将 $(b)$ 整体减去一个 $k$ 从而消掉 $r_n$ ,这样一来可以表示为 $x_n = 2 ^ {n - 2}(a + k) + r$ ,令 $r$ 的二进制表示为 $d_{n - 3}d_{n - 4} \dots d_0$ ,此时 $r_{i(i < n)} = k + d_{n - i - 1}$ ,$r_n = k$ 。

然后暴力输出 $x$ 序列即可。

代码

https://pasteme.cn/8173

#include <bits/stdc++.h>
const int maxn = 54;
typedef long long ll;
ll __pow[maxn] = {1}, r[maxn], a, b, m;
int solve() {
    if (a == b) return 1;
    for (int n = 2; __pow[n - 2] <= b; n++) {
        ll div = b / __pow[n - 2], mod = b % __pow[n - 2];
        if (div > a && (div - a < m || (mod == 0 && div - a <= m)) && __pow[n - 2] - 1 >= mod) {
            for (int i = 2, bit = n - 3; bit >= 0; i++, bit--) r[i] = (mod >> bit & 1) + div - a;
            return n;
        }
    }
    return -1;
}
ll calc(int x, int n) {
    if (x > 1 && x < n) {
        ll ret = __pow[x - 2] * a;
        for (int i = 2; i < x; i++) ret = ret + __pow[x - i - 1] * r[i];
        return ret + r[x];
    } else return x == 1 ? a : b;
}
int main() {
    int q, n;
    for (int i = 1; i < maxn; i++) __pow[i] = __pow[i - 1] << 1;
    for (scanf("%d", &q); q; q--) {
        scanf("%lld%lld%lld", &a, &b, &m);
        if (~(n = solve())) {
            printf("%d ", n);
            for (int i = 1; i <= n; i++) printf("%lld%c", calc(i, n), i == n ? '\n' : ' ');
        } else puts("-1");
    }
    return 0;
}
最后修改:2019 年 05 月 19 日
谢谢老板!