Codeforces - 1166D - Cute Sequences

Codeforces - 1166D - Cute Sequences

地址

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

原文地址

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

题目

Given a positive integer m m m, we say that a sequence x 1 , x 2 , … , x n x_1, x_2, \dots, x_n x1,x2,,xn of positive integers is m m m-cute if for every index i i i such that 2 ≤ i ≤ n 2 \le i \le n 2in it holds that x i = x i − 1 + x i − 2 + ⋯ + x 1 + r i x_i = x_{i - 1} + x_{i - 2} + \dots + x_1 + r_i xi=xi1+xi2++x1+ri for some positive integer r i r_i ri satisfying 1 ≤ r i ≤ m 1 \le r_i \le m 1rim.

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

题意

定义 x i = x i − 1 + x i − 2 + ⋯ + x 1 + r i x_i = x_{i - 1} + x_{i - 2} + \dots + x_1 + r_i xi=xi1+xi2++x1+ri 1 ≤ r i ≤ m 1 \le r_i \le m 1rim ,给你 a b m ,判断是否存在一个一个序列 x x x ,假定这个序列的长度为 n n n ,使得 x 1 = a x_1 = a x1=a x n = b x_n = b xn=b

题解

规定 2 x = 0 2 ^ {x} = 0 2x=0 ( x < 0 ) (x < 0) (x<0) ,归纳一下,可以发现: (a) x n ( n ≥ 2 ) = 2 n − 2 a + 2 n − 3 r 2 + 2 n − 4 r 3 + ⋯ + 2 r n − 2 + r n − 1 + r n   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} xn(n2)=2n2a+2n3r2+2n4r3++2rn2+rn1+rn (a)

即判断是否存在一个 x n x_n xn 满足 ( a ) (a) (a) 式且 x n = b x_n = b xn=b

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

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

代码

https://pasteme.cn/8173

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

你可能感兴趣的:(ACM,题解,Codeforces,构造)