主要思路为 通过异或交换律, i^j = x, j = i^x, 来找成立得二元组{i, j}
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define debug cout<<"debug"<<endl
typedef long long ll;
typedef long double ld;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = 3.14159265358979323;
const int N = 2e5+10, M = 2*N, mod = 998244353;
const int INF = 0x3f3f3f3f;
int n, k, x;
void solve()
{
cin>>n>>k>>x;
int sum = 0;
int v[n+1];
for(int i = 1; i<=n; i++) sum^=i, v[i] = 0;
// 一共n组, 通过计算异或和就能判断是否存在答案
if(sum != (k&1 ? x : 0))
{
cout<<"NO"<<endl;
return;
}
if(k == 1)
{
cout<<"YES"<<endl<<n<<" ";
for(int i = 1; i<=n; i++) cout<<i<<" \n"[i==n];
return;
}
vector<vector<int>> p;
// 因为一定存在答案, 我们就可以两两分组, 利用异或得交换律 i^j = x, j = i^x, 来找到所有成立得二元组
// 最后除了单个x, 剩下得所有数一定能异或成x, 因为答案一定存在
// 最后选出前k-1组, 剩下数自成一组即可
for(int i = 1; i<=n; i++)
{
if(i == x || v[i]) continue;
if((x^i) <= n)
{
v[i] = v[x^i] = 1;
p.push_back({i, x^i});
}
}
vector<int> a;
for(int i = 1; i<=n; i++)
{
if(i == x || v[i]) continue;
a.push_back(i);
}
if(a.size()) p.push_back(a);
if(x<=n) p.push_back({x});
int cnt = p.size();
if(cnt>=k)
{
cout<<"YES"<<endl;
int sz = 0;
k--;
int i;
for(i = 0; i<p.size() && k; i++, k--)
{
sz += p[i].size();
cout<<p[i].size()<<" ";
for(auto t : p[i]) cout<<t<<" ";
cout<<endl;
}
cout<<n-sz<<" ";
for( i; i<p.size(); i++)
{
for(auto t : p[i]) cout<<t<<" ";
}
cout<<endl;
}else cout<<"NO"<<endl;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int T;
T = 1;
cin>>T;
while(T -- )
{
solve();
}
return 0;
}