E. The Harmonization of XOR(异或构造 2100

Problem - E - Codeforces

题意:给你三个参数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();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值