题意:给你三个参数n,k,x; 也就是n长的排列,要构造出k个序列满足不相交且异或值恰好为x,不满足输出NO
分析:当时马上就能想到首先这个不满足的条件之一就是根据奇偶性和1~n的所有异或值累异或,如果不等直接NO;
但是后面一下子就不知道如何构造了,所以解题的关键点还是要发现思考的方向,【问题的关键取决于最大能构造的个数】,同时我们也会发现如果第一个条件是满足的情况下,那么构造一个确切的个数只要把剩下的全部放在一起就行了(利用了异或的性质);那么越多越好就是尽可能22组合。开个桶就行,所以是利用异或性质贪心构造,一开始想偏了;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 15;
const int mo = 998244353;
#define pb push_back
#define pii pair<int,int>
#define ft first
#define sd second
#define ffor(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
#define rfor(i,a,b,c) for(int i=(a);i>(b);i-=(c))
#define Rfor(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
#define all(x) (x).begin(), (x).end()
#define debug1(x) cerr<<"! "<<x<<endl;
#define debug2(x,y) cerr<<"# "<<x<<" "<<y<<endl;
void slv() {
int n, k, x; cin >> n >> k >> x;
vector<int>vis(n + 1);
int final = (k & 1 ? x : 0), sm = 0;
For(i, 1, n, 1) {
sm ^= i;
}
if (sm != final) {
cout << "NO\n";
return;
}
vector<pii>ans;
For(i, 1, n, 1) {
if (i == x) {
vis[x] = 1;
ans.pb({x, 0}); continue;
}
if (vis[i] || ((i ^ x) > n)) continue;
if (vis[i ^ x])continue;
ans.pb({i, i ^ x});
vis[i] = vis[i ^ x] = 1;
}
int flg = 0;
For(i, 1, n, 1) {
if (!vis[i]) {
flg = 1;
}
}
if (ans.size() + flg < k) {
cout << "NO\n"; return;
}
cout << "YES\n";
For(i, 0, k - 2, 1) {
if (ans[i].ft == x) {
cout << 1 << " " << ans[i].ft;
cout << '\n';
continue;
}
cout << 2 << " " << ans[i].ft << " " << ans[i].sd << '\n';
}
vector<int>tmp;
For(i, k - 1, ans.size() - 1, 1) {
tmp.pb(ans[i].ft);
if (ans[i].ft == x) continue;
tmp.pb(ans[i].sd);
}
For(i, 1, n, 1)if (!vis[i]) {
tmp.pb(i);
}
if (tmp.size()) {
cout << tmp.size() << " ";
for (auto x : tmp) cout << x << ' ';
}
cout << '\n';
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int t; cin >> t;
while (t--) {
slv();
}
}