Increasing Sequence with Fixed OR(使用固定 OR 递增序列)

题目

You are given a positive integer n𝑛. Find the longest sequence of positive integers a=[a1,a2,…,ak]that satisfies the following conditions, and print the sequence:
你得到一个正整数 n 。找到满足以下条件的最长正整数 a=[a1,a2,…,ak] 序列,并打印该序列:

  • ai≤n for all 1≤i≤k.
    ai≤n 对于所有 1≤i≤k .
  • a𝑎 is strictly increasing. That is, ai>ai−1 for all 2≤i≤k.
    a𝑎 正在严格增加。也就是说, ai>ai−1 对于所有 2≤i≤k .
  • ai|ai−1=n for all 2≤i≤k, where || denotes the bitwise OR operation.
    ai|ai−1=n for all 2≤i≤k ,其中 || 表示按位 OR 运算。

Input 输入

Each test contains multiple test cases. The first line contains the number of test cases t𝑡 (1≤t≤1000). Description of the test cases follows.
每个测试都包含多个测试用例。第一行包含测试用例 t𝑡 的数量 ( 1≤t≤1000 )。测试用例的说明如下。

The only line of each test case contains one integer n𝑛 (1≤n≤1e18).
每个测试用例的唯一一行包含一个整数 n𝑛 ( 1≤n≤1e18 )。

It's guaranteed that the sum of lengths of the longest valid sequences does not exceed 5⋅1e5.
可以保证最长有效序列的长度总和不超过 5⋅1e5

Output 输出

For each testcase, print two lines. In the first line, print the length of your constructed sequence, k𝑘. In the second line, print k𝑘 positive integers, denoting the sequence. If there are multiple longest sequences, you can print any of them.
对于每个测试用例,打印两行。在第一行中,打印构造序列 的长度 k 。在第二行中,打印 k 正整数,表示序列。如果有多个最长的序列,则可以打印其中任何一个。

Example 例

input 输入

4
1
3
14
23

output 输出

1
1
3
1 2 3
4
4 10 12 14
5
7 18 21 22 23

分析

本题要求寻找所有比n小的数 并且与n按位能进行或运算。

首先定义lowbit(x)为x&(-x)作用为找到x二进制的第一位1 比如20的二进制为10100 经lowbit运算后的到的a的二进制为100也就是4 再判断4不等于n 所以就将a=4存入vector中 表示这个值是我们所需要的序列中的元素 最后用reverse函数将v中的数组反转 再输出v中全部元素即可

知识点

熟记二进制按位运算(详细学习可以参考这个大佬的博客挺全面的) 然后用reverse函数进行反转数组 最后使用auto输出

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
#define lowbit(x) x&(-x)//获得二进制中最低位的1

ll t,n;

int main()
{
    cin>>t;
    while(t--)
    {
        vector<ll> v;
        cin>>n;
        v.push_back(n);
        ll m=n;
        while(m)
        {

            ll a=lowbit(m);
            m-=a;
            if(n-a)
                v.push_back(n-a);
        }
        cout<<v.size()<<endl;
        reverse(v.begin(),v.end());//反转数组
        for(auto i:v)
            cout<<i<<" ";
        cout<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值