Problem
Ostad thinks that the usual way of factoring numbers is too mathematical, so he invented a new notion called XOR-factorization , which is more computer-science-like. For a given integer n n n, a sequence of integers a 1 , a 2 , ... , a k a_1, a_2, \dots, a_k a1,a2,...,ak with 0 ≤ a i ≤ n 0 \le a_i \le n 0≤ai≤n for all i i i is called a XOR-factorization of n n n if and only if
a 1 ⊕ a 2 ⊕ ⋯ ⊕ a k = n , a_1 \oplus a_2 \oplus \dots \oplus a_k = n, a1⊕a2⊕⋯⊕ak=n,
where ⊕ \oplus ⊕ denotes the bitwise XOR operation.
You are given integers n n n and k k k. Find a XOR-factorization a 1 , a 2 , ... , a k a_1, a_2, \dots, a_k a1,a2,...,ak of n n n that maximizes the sum a 1 + a 2 + ⋯ + a k a_1 + a_2 + \dots + a_k a1+a2+⋯+ak.
It can be proven that under the problem conditions, a XOR-factorization always exists.
Input
Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 10 4 1 \le t \le 10^4 1≤t≤104). The description of the test cases follows.
Each of the next t t t lines contains two integers n n n and k k k ( 1 ≤ n ≤ 10 9 , 1 ≤ k ≤ 10 5 1 \le n \le 10^9, 1 \le k \le 10^5 1≤n≤109,1≤k≤105).
It is guaranteed that the sum of k k k over all test cases does not exceed 10 5 10^5 105.
Output
For each test case, output k k k integers a 1 , a 2 , ... , a k a_1, a_2, \dots, a_k a1,a2,...,ak such that 0 ≤ a i ≤ n 0 \le a_i \le n 0≤ai≤n.
We can show that an answer always exists. If there are multiple valid answers, you may print any of them in any order.
Translation
Ostad 认为传统的数字分解方式太过于数学化,因此他发明了一个更具计算机科学风格的新概念,称为 XOR-分解 。对于给定的整数 n n n,如果一个由整数组成的序列 a 1 , a 2 , ... , a k a_1, a_2, \dots, a_k a1,a2,...,ak 满足对于所有的 i i i 都有 0 ≤ a i ≤ n 0 \le a_i \le n 0≤ai≤n,那么当且仅当满足以下条件时,该序列被称为 n n n 的一个 XOR-分解:
a 1 ⊕ a 2 ⊕ ⋯ ⊕ a k = n , a_1 \oplus a_2 \oplus \dots \oplus a_k = n, a1⊕a2⊕⋯⊕ak=n,
其中 ⊕ \oplus ⊕ 表示按位异或运算。
给定整数 n n n 和 k k k。请找到一个 n n n 的 XOR-分解 a 1 , a 2 , ... , a k a_1, a_2, \dots, a_k a1,a2,...,ak,使得总和 a 1 + a 2 + ⋯ + a k a_1 + a_2 + \dots + a_k a1+a2+⋯+ak 最大。
可以证明,在题目给出的条件下,XOR-分解 总是存在的。
输入格式
每个测试包含多个测试用例。第一行包含测试用例的数量 t t t ( 1 ≤ t ≤ 10 4 1 \le t \le 10^4 1≤t≤104)。接下来的内容是测试用例的描述。
接下来的 t t t 行中,每行包含两个整数 n n n 和 k k k ( 1 ≤ n ≤ 10 9 , 1 ≤ k ≤ 10 5 1 \le n \le 10^9, 1 \le k \le 10^5 1≤n≤109,1≤k≤105)。
保证所有测试用例中 k k k 的总和不超过 10 5 10^5 105。
输出格式
对于每个测试用例,输出 k k k 个满足 0 ≤ a i ≤ n 0 \le a_i \le n 0≤ai≤n 的整数 a 1 , a 2 , ... , a k a_1, a_2, \dots, a_k a1,a2,...,ak。
我们可以证明答案总是存在的。如果存在多个有效的答案,你可以按任意顺序打印其中的任意一个。
Solutions
Approach 1
位运算性质 + 讨论。
显然,当 n 为奇数时最优解为 a 1 = a 2 = ⋯ = a k = n a_1 = a_2 = \cdots = a_k = n a1=a2=⋯=ak=n 。于是以下讨论中 k k k 都为偶数。
既然位运算,那么依旧按位考虑,这里因为涉及求和,高位影响大,所以先从 n n n 二进制下的最高位考虑,以下不妨假设 a 1 ⩾ a 2 ⩾ ⋯ ⩾ a k a_1 \geqslant a_2 \geqslant \cdots \geqslant a_k a1⩾a2⩾⋯⩾ak 。
对于最高位,显然选择是唯一的,除了 a k a_k ak 是 0 ,其余在该位都是 1 。注意到 a i ⩽ n a_i \leqslant n ai⩽n 的限制,此时 a 1 ∼ a k − 1 a_1 \sim a_{k-1} a1∼ak−1 都是贴合 n n n 的,只有 a k a_k ak 是小于 n n n 的。
考虑第二位,如果 n n n 在此位是 0 ,那么证明有偶数个 1 ,但是由于 a i ⩽ n a_i \leqslant n ai⩽n 的限制, a 1 ∼ a k − 1 a_1 \sim a_{k-1} a1∼ak−1 都不能填 1 ,只有 a k a_k ak (即小于 n n n 的位置) 可以,但只有 1 个,所以这里全部都为 0 ,而与 n n n 的贴合关系没有变化。
那如果 n n n 在此位是 1 ,那么证明有奇数个 1 ,由于 k k k 是偶数,需要将一个 1 变为 0 ,而为了最优化,显然是要将一个贴合 n n n 的变为小于 n n n ,于是最优解是 a 1 ∼ a k − 2 a_1 \sim a_{k-2} a1∼ak−2 和 a k a_k ak 为 1 , a k − 1 a_{k-1} ak−1 为 0 。此时有两个小于 n 的位置。
第三位类似,只不过如果是 0 时,有了 2 个小于 n n n 的位置,可以填上 1 。
总之,如果 n n n 是 0 ,那么从小于 n n n 的位置选择偶数个且尽可能多的填 1 ,否则,将一个贴合 n n n 的变为小于 n n n ,当都小于 n n n 时,留一个位置为 0 即可。
那可能在某一位将额外的 1 变成 0 来使得小于 n n n 的位置更多进而增加答案吗?不可能,纵览贪心过程,其后的额外最大收益无非就是该位置之后的每一位都能填 1 ,这不会大于此位的值。
与题解 Codeforces Global Round 31 - Codeforces 类似。
Code
cpp
#include<bits/stdc++.h>
using namespace std;
std::mt19937 rng(std::random_device{}());
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
#define sig(x) (x >= 0 ? 1 : -1)
const int mod = 998244353;
const double ept = 1e-9;
ll add(ll x, const ll&y) { x += y; if(x >= mod) { x -= mod; } return x; }
ll sub(ll x, const ll&y) { x -= y; if(x < 0) { x += mod; } return x; }
ll mul(ll x, const ll&y) { x = x * y; if(x >= mod) { x %= mod; } return x; }
#ifndef ONLINE_JUDGE
#define DEBUG 1
#define fastio
#define coutd cout
#define db(i) cout << #i << ": " << i << endl;
#define dbl(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__);
#define dbi(vec) { cout << #vec << ": "; for(auto &v: vec) { cout << v << ' '; } cout << endl; }
#define dbv(vec, a, b) { cout << #vec << ": "; for(int i=a; i!=b+sig(b-a); i+=sig(b-a)) { cout << vec[i] << ' '; } cout << endl; }
#else
#define DEBUG 0
#define fastio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define coutd cerr
#define db(...)
#define dbl(fmt, ...)
#define dbi(vec)
#define dbv(vec, a, b)
#endif
int n, k;
int ans[100100];
void solve(int T) {
cin >> n >> k;
for(int i=1; i<=k; i++) ans[i] = 0;
if(k & 1) {
for(int i=1; i<=k; i++) cout << n << ' ';
cout << endl;
} else {
int r = 0;
for(int i=30; i>=0; i--) {
if((n>>i) & 1) {
for(int j=1; j<=k; j++) {
if(j + r == k) continue;
if(r >= k && j == 1) continue;
ans[j] += (1<<i);
// cout << i << ' ' << j << ' ' << ans[j] << endl;
}
++r;
}
else {
for(int j=k-1; j>=k-r+1 && j>=1; j-=2) {
ans[j] += (1<<i);
ans[j+1] += (1<<i);
}
}
}
for(int i=1; i<=k; i++) cout << ans[i] << ' ';
cout << endl;
}
}
void init() {}
signed main() {
//freopen("1.in", "r", stdin);
//freopen("1.out", "w", stdout);
//cout.flags(ios::fixed); cout.precision(8);
fastio
init();
int T_=1;
std::cin >> T_;
for(int _T=1; _T<=T_; _T++) { solve(_T); }
return 0;
}