C++,codeforces, 2072C,C. Creating Keys for StORages Has Become My Main Skill

/*
codeforces, 2072C,C. Creating Keys for StORages Has Become My Main Skill
给两个数n,x
要求给出一个长度为n的数组,其中
    数组中所有元素的或运算结果等于x
    数组的MEX()最大,
    MEX()是指数组中不包含的最小非负整数,比如[0,1,2,3,4]的MEX()是5,[0,1,3,4]的MEX()是2
输入:
    第一行一个整数t,表示有t组数据
    接下来t行,每行两个整数n,x
输出:
    对于每组数据,输出一个长度为n的数组,满足条件
*/

/*
若要MEX()最大,则数组中的数应尽量是从0开始连续的数,即0,1,2,3,4...
同时,若要保证数组元素或运算结果为x,
则x的二进制表示中,1的位数一定要有至少一个元素该位为1,0的位数所有元素该位均为0
从0开始的连续的数的或运算的结果一定是连续的1
则数组中连续的数不能超过x的二进制表示中尾部连续1的值
假如x为: 1010011101111
则连续的数最多为, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14(1110),15(1111)
之后的16(10000)会导致或运算结果中应该为0的位数为1

最后应尽量将上面的连续数装入数组中,最后若连续数不能或运算成为x,
则还需在数组中空出一位放入x,使得或运算结果为x
若还有空余的位置,放置0即可

*/
#include <iostream>
#include <string>
int bitlength(int x){
    int bits = 0;
    while(x){
        x>>=1;
        bits++;
    }
    return bits;
}
void solve(){
    long long n,x;std::cin>>n>>x;
    long long neededDight = std::to_string(x).size();
    if(n==1){
        std::cout<<x;
    }else{
        long long count = 0;
        /*
        从0开始遍历到n-2,先保留数组中最后一个位置,填充前n-1个位置,
        判断连续的数是否小于等于x尾部的连续1,可使用(x|i)==x判断再x尾部第一个0的位置,i在该位是否为1
        若可用的连续的数已用完,或者前n-1个位置填充满,退出循环
        */
        for(;count<=(n-2) && count<=x;count++){
            if((count|x) == x){
                std::cout<<count<<' ';
            }else{
                break;
            }
        } 
        if(count<=(n-1)){
            //先决定保留的一位是应该填充x还是最后一个连续数
            int countBit = bitlength(count);
            int xBit = bitlength(x);
            //count is      1..00... 
            //x  is   ...xxxx111...
            if(countBit>xBit){
                //已经输出的连续的数正好能或运算成为x,不需要添加其它数,之后将空位补充为0即可
                //count is      1000... 
                //x  is   ...0000111...
            }else if(countBit==xBit){
                //已经输出连续的数加上这一个count(由于只剩一个空位还未输出)正好能或运算成为x
                //则不需要保留位置给x,之间输出count
                //count is      1..00... 
                //x  is     ..001111...
                std::cout<<count<<' ';
                ++count;
            }else if(countBit<xBit){
                //连续的数不能或运算成为x,保留一个空位给x,
                //之后将剩余的空位补位0
                //count is      1000... 
                //x  is .x1x...x1111...
                //x  is .x1x...x0111...
                std::cout<<x<<' ';
                ++count;
            }
            for(;count<=(n-1);count++){
                std::cout<<0<<' ';
            }
        }
    }
    std::cout<<std::endl;
}
int main(){
    long long t;std::cin>>t;
    while(t--){
        solve();
    }
}
posted @ 2025-02-27 13:11  Kazuma_124  阅读(35)  评论(0)    收藏  举报