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

Little_x_starTYJ
愿时光能缓,愿故人不散! || 众所周知,如果把灯泡放在嘴里,即使你自己一个人也取得出来灯泡。搬运于
2025-08-24 23:12:13,当前版本为作者最后更新于2025-06-29 11:54:30,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
前言
把此题放到 T4 然后模拟考最为期末成绩,目前感觉快 AFO 了。最后 。想要考试的四道原题的家人们可以私信我要题号。
解题思路
防止读者在阅读时忘记 时什么意思,所以就放在这里了。
表示整数 的二进制表示中 的位数。例如,,。
乍眼一看似乎很不可做的样子,实则因人而异。
赛时看到异或,首先想到 01trie,然后想了一阵发现不会,于是就没想了。
赛后瞅一眼题解,发现了一条重要性质:。我赛时怎么没想到!
相信大家看到题目可能会先想着去构造序列 ,使得其满足 吧,但是这样很难再进行构造使得 $\text{popcount}(a_1) \oplus \text{popcount}(a_2) \oplus \cdots \oplus \text{popcount}(a_N) = K$,所以我们可以先使得其满足条件 ,再来想办法让其满足条件 。
我们先构造一个满足条件的序列 ,使此序列的和最小(不是异或和)。其实我们并不需要考虑类似 的情况,我们要求和最小就是为了避免初步构造时出现上述复杂情况(因为如果这些数的某一位上重复出现很多次 ,那么它们的总和一定不是最小的,我们可以使得这一位只出现 次或 次 来达到同样的效果),即我们需要一步一步来,不能做到一步到位。
怎么构造和最小且满足条件 的序列呢?想到异或与二进制有关,因此可以考虑对于 进行二进制分解。这一步可能有点绕且难以描述,所以我们以第二组数据进行模拟再进行解释。
,首先二进制分解 得到 ,向答案数组里面添加 ,因为第一个 代表 ,所以得到 。
为什么要这么做?别忘了 代表的是所有数在二进制下 的个数的和,那么将其二进制拆分则代表第 个数的 的个数为 ,那么最小的数即 。
那么我们选出来的这些数即我们的初始元素。将 减去这些数的和,记为 。
- 如果 ,显然无解。
- 否则如果 ,那么我们构造的 已经同时满足条件 了,直接输出即可。
- 否则如果 ,则我们还差 才能同时满足条件 。
-
- 如果已构造出来的序列中有 ,由于 ,所以我们可以将序列中的 变成 来达到条件。
-
- 如果已构造出来的序列中没有 ,那么一定无解,因为不存在某个数与序列中的所有数同时满足为 且 。
- 否则如果 为偶数,直接往答案序列中加入两个 即可(两个相同的数异或后值为 ,不影响条件 )。
- 否则即 为奇数,由于 且 ( 的情况处理过了),因此我们可以从 中取出来一个 和 就可以将 转化为偶数的情况。(因为取出来一个 虽然可能会导致 的二进制排列差异过大,但是取出来一个 和 过后,后面两个数都为 ,异或后为 ,前面只有 且 ,所以 ,,所以此方案可行。)
对于条件 就懒得说了,大家可以看看代码,满打满算 。
如果本题解有什么写错的地方可以在评论区踹我一脚,我好修改,没看懂的也可以踹我一脚,我好写得更详细。
CODE:
#include <bits/stdc++.h> using namespace std; #define int long long vector<int> v; signed main() { ios::sync_with_stdio(false); ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0); int T; cin >> T; while (T--) { int m, k, sum = 0; cin >> m >> k; bool flag1 = false; v.clear(); for (int i = 5; i >= 1; i--) { int p = (1 << i); if (k >= p) { k -= p; v.emplace_back((1 << p) - 1); //emplace_back = push_back,据说跑得要快点而已。 sum += (1 << p) - 1; } } if (k) { flag1 = true; v.emplace_back(1); sum++; } if (sum > m) { cout << "-1\n"; continue; } m -= sum; if (m == 1) { if (flag1) { v.pop_back(); v.emplace_back(2); } else { cout << "-1\n"; continue; } } else if (m) { if (m & 1) { v.emplace_back(1); v.emplace_back(2); if (m > 3) { v.emplace_back((m - 3) / 2); v.emplace_back((m - 3) / 2); } } else { v.emplace_back(m / 2); v.emplace_back(m / 2); } } cout << v.size() << "\n"; for (auto u : v) { cout << u << ' '; } cout << "\n"; } return 0; }
- 1
信息
- ID
- 11904
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者