AT ARC200D |A + A|
cnblogs。
首先让
接下来进行一些尝试,发现
那么
上面的构造看起来比较优美,于是考虑从这个基础上调整
毕竟刚刚的选取都是正着选的,为什么不能倒着选呢?
考虑到
如果选取
不过如果选取
接下来就是去分析使用的条件了,经过一定的分讨,或者可以自己代入一些值模拟,会知道
首先对于
接下来考虑
- 当选出
1 个数时,最多只有1 种组合,必然凑不出2 种,不合法。 - 当选出
\ge 3 个数(x, y, z, \cdots) 时,x + x, x + y, x + z 必然不同,于是至少有3 种和,不合法。
对于选出
根据刚刚的经验,可以知道对于
- 当选出
3 个数0, x, y 时,0, x, y 本身不同,所以2x, 2y, x + y 中需要有2 个值与0, x, y 中的某个值相等,考虑继续分讨: -
- 当选出
4 个数0, x, y, z 时,0, x, y, z 本身不同,所以2x, 2y, 2z 都必须和0, x, y, z 中的某个值相等,于是分讨: -
经过刚刚的分讨,可以知道只有当
时间复杂度
#include <bits/stdc++.h>
inline void solve() {
int m, k;
scanf("%d%d", &m, &k);
std::vector<int> ans;
if (k % 2 == 1) {
for (int i = 0; i <= (k - 1) / 2; i++) ans.push_back(i);
} else if (k == m) {
for (int i = 0; i < m; i++) ans.push_back(i);
} else if (k == 2) {
if (m % 2 != 0) {
return puts("No"), void();
} else {
ans = {0, m / 2};
}
} else if (k >= 6) {
for (int i = 0; i <= (k - 4) / 2; i++) ans.push_back(i);
ans.push_back(m - 2);
} else if (m % 4 == 0) {
ans = {0, m / 2, m / 4};
} else {
return puts("No"), void();
}
puts("Yes");
printf("%zu\n", ans.size());
for (int x : ans) printf("%d ", x);
puts("");
}
int main() {
int t; scanf("%d", &t);
while (t--) solve();
return 0;
}