1 条题解
-
0
自动搬运
来自洛谷,原作者为

Alex_Wei
**搬运于
2025-08-24 22:52:45,当前版本为作者最后更新于2024-02-09 13:54:15,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P9890 [ICPC2018 Qingdao R] Tournament
构造好题。
因为任意一组构造在 变小时依然适用,所以我们需要对每个 找到有解的 的最大值。
正向构造:
- 第一步:两两配对。因为编号可以任意排列,所以 和 匹配是字典序最小的。如果不是 的倍数,则办不到。
- 第二步:若 和 配对,则 和 配对;反之若 和 配对,则 和 配对。这相当于将 和 看成一组,两组之间配对,总共可以贡献两轮。如果不是 的倍数,则办不到。
- 以此类推,第 步会将第 步的大小为 的结构两两匹配,形成大小为 的结构并贡献 轮,要求 。
综上,设 为最大的能整除 的 的幂,即 在二进制下最低位的 ,则 。注意上述推导只是感性理解,不构成严谨证明。可以尝试通过 “题述限制要求小结构合并时必须成对,得到大结构的大小为 的幂” 的思路进行证明,具体细节留给读者思考。
反向构造:设 表示 和 在第 轮决斗,则题述要求等价于:若 且 ,则 。根据 的该种性质,容易想到一个合理的二元运算符:异或。令 ,则 在第 轮的对手为 。这给出了 时的构造:当 时,$((n - 1)\oplus 2 ^ p) + 1 = ((n - 1) + p) + 1 = n + p$,不合法。
容易证明这样构造得到的是字典序最小解。
时间复杂度 。
#include <bits/stdc++.h> using namespace std; using ll = long long; using pii = pair<int, int>; using pll = pair<ll, ll>; using pdi = pair<double, int>; using pdd = pair<double, double>; using ull = unsigned long long; using LL = __int128_t; #define ppc(x) __builtin_popcount(x) #define clz(x) __builtin_clz(x) bool Mbe; // ---------- templates above ---------- int n, k; void solve(int T) { cin >> n >> k; if(k >= (n & -n)) cout << "Impossible\n"; else { for(int i = 1; i <= k; i++) { for(int a = 1; a <= n; a++) { cout << ((a - 1) ^ i) + 1 << " "; } cout << "\n"; } } } bool Med; signed main() { fprintf(stderr, "%.3lf MB\n", (&Mbe - &Med) / 1048576.0); // ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); #ifdef ALEX_WEI FILE* IN = freopen("1.in", "r", stdin); FILE* OUT = freopen("1.out", "w", stdout); #endif int T = 1; cin >> T; while(T--) solve(T); fprintf(stderr, "%.3lf ms\n", 1e3 * clock() / CLOCKS_PER_SEC); return 0; } /* g++ a.cpp -o a -std=c++14 -O2 -DALEX_WEI */
- 1
信息
- ID
- 9445
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者