位运算或和MEX

Creating Keys for StORages Has Become My Main Skill

例如,代码为(n,x) 的存储空间的密钥是一个长度为 n 的数组 a ,

  • a1 | a2 | a3 | … | an=x 其中 a | b是数字 a 和 b 的按位 " OR"

  • 在所有这样的数组中, 要使得MEX({a1,a2,a3,…,an})是最大值。

    ∗ MEX(S) 是最小的非负整数 z ,使得 z 不包含在集合 S 中,且所有 0≤y<z 都包含在 S 中。

输入

第一行包含 t ( 1≤t≤1e4 ) - 测试用例数。

在每个测试用例的唯一一行中,给出了两个数字 n 和 x( 1≤n≤2⋅105,0≤x<230)。

保证所有测试用例中 n 的总和不超过 2e5。

输出

针对每个测试用例,输出 n 个整数 ai( 0≤ai<2^30 )。

如果有多个合适的数组,则输出其中任意一个。

分析

本来是想求末位有几个连续的1...但是这并不是个好思路,处理起来也异常复杂,需要非常细致的分类讨论

1200的题真的有这么大的码量吗? 显然我的思路并不是最优解, 于是还是点开了洛谷题解, 来自作者tzzl3035

从 0 开始向后枚举,若或上这个数不会使最终的 x 改变,则加上这个数,否则不枚举了。若枚举完后发现按位或的和不够 x,把最后一位改为 x 即可。

if((i|x)==x) 注意这里的位运算必须加上括号,建议所有的位运算都用括号包起来

ac代码

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define int long long

const int N=3e5+5;

void solve(){
    int n,x;cin>>n>>x;
    vector<int> v;
    int sum=0;
    for(int i=0;i<=n-1;i++){
        if((i|x)==x){  // 不得不说这一行挺巧妙的, 省去了处理一个二进制数末位1的个数的复杂讨论
            v.push_back(i);
            sum|=i;
        }else{
            break;
        }
    }
    if(v.size()<n){
        while(v.size()<n)v.push_back(x);
        for(auto i:v)cout<<i<<' ';
        cout<<endl;
    }else{
        if(sum!=x){
            v.pop_back();
            v.push_back(x);
        }
        for(auto i:v)cout<<i<<' ';
        cout<<endl;
    }
}

signed main(){
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int _;cin>>_;while(_--)
    solve();
    return 0;
}

题目来自Codeforces Round 1006 (Div. 3) C. Creating Keys for StORages Has Become My Main Skill

posted @ 2025-03-08 20:29  byxxx  阅读(31)  评论(0)    收藏  举报