题解:P12025 [USACO25OPEN] Sequence Construction S

· · 题解

题意简述

构造序列使得:

若无解输出 -1

基本思路

因为 k 是一堆东西的异或和,不难想到对 k 进行二进制分解。

k=5 为例,(5)_{10} = (101)_{2}

对于第一位 1,它由一个 x 满足 \text{popcount}(x) = 4 贡献而来,这个 x 最小为 2^4-1 = 15,故我们将 15 加入序列,同样的对于最后一位 1,将 2^1-1=1 加入序列。

该样例对应的 m=33,减去 151 后还剩下 17

我们需要之后的元素 1 的个数异或和为 0

对于一个偶数,直接取两个 $n \div 2$ 则满足条件。 考虑无解情况,若 $m$ 在某一步小于了 $0$,则无解。 若剩余的 $m$ 为 $1$,如果当前序列有一个 $1$,改为 $2$ 可以凑出一组解,否则无解。 ## AC Code ```cpp #include <bits/stdc++.h> #define F(i, a, b) for (int i = a; i <= b; ++i) #define _F(i, a, b) for (int i = a; i >= b; --i) #define ll long long using namespace std; ll rd() { ll p = 0, f = 1; char ch = getchar(); while (ch>'9' || ch<'0') { if (ch == '-') f = -1; ch = getchar(); } while (ch>='0' && ch<='9') p = p*10+ch-'0', ch = getchar(); return p * f; } ll m, k, a[110], tot = 0; void Solve() { tot = 0; m = rd(), k = rd(); _F(i, 5, 0) { if (k & (1<<i)) { ll cur = (1<<(1<<i))-1; m -= cur, a[++tot] = cur; if (m < 0) { cout << -1 << '\n'; return ; } } } if (m == 1) { if (a[tot] != 1) { cout << -1 << '\n'; return ; } ++a[tot]; } else if (m % 2 == 0) { a[++tot] = m/2, a[++tot] = m/2; } else { a[++tot] = 1, a[++tot] = 2, a[++tot] = (m-3)/2, a[++tot] = (m-3)/2; } cout << tot << '\n'; F(i, 1, tot) cout << a[i] << ' '; cout << '\n'; } int main() { ll T = rd(); while (T--) Solve(); return 0; } ```