codeforces 958 c 题解
题目链接
AC代码
题目大意: 构造一个严格单调递增的序列a, 满足 a[i-1] | a[i]=n,1<= i <= len-1(len为序列的长度)
涉及到位运算的题目,我们可以拆成二进制的表示来思考,根据异或的性质,在n的某一位为1的情况下,a[i-1]和a[i]必须有一个的这一位为1,要想len最大,则可以一次从高位往低位看,每次只将这一位的1变成0输出即可。注意到当只存在1位为1的情况是只能为n;
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define pii pair<int, int>
#define mp make_pair
#define fi first
#define se second
#define all(v) v.begin()+1, v.end()
#define ull unsigned long long
#define sz(s) ((int)s.size())
constexpr int N = 1000000+ 10, mod = 1e9+7;
inline void solve(){
ll n;
cin>>n;
int cnt=__builtin_popcountll(n);//统计1的个数
if(cnt==1){
cout<<1<<"\n";
cout<<n<<"\n";
return ;
}
cout<<cnt+1<<"\n";
for(int i=59;i>=0;i--){//1e18最大为2^59,将越前面的1变0的数越小
if(n>>i & 1){
cout<<(n ^ (1ll<<i))<<" ";//1^1=0, 1变0,(1ll<i)这里注意
}
}
cout<<n<<"\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}```
相关知识
最低位1后面有多少个0
__builtin_ctz()//int
__builtin_ctzll()//unsigned long long
有多少个1
__builtin_popcount()//int
__builtin_popcountll()//unsigned long long
x << i x * pow(2, i)
x >> i x / pow(2, i)
t |= 1<< (x-1);//t的x位赋为1,这里最低位为1 x=2,5 0010010,状压
t>>(x-1)///判断t的x位,这里最低位为1
(n ^ (1ll << i))将n的第i位1变成0后的数