← 返回

CF1988C Increasing Sequence with Fixed OR 题解

CF1988C

题意简述

给定一个正整数 $n$,要构造出一个长度为 $k$ 的严格递增序列 $a$,且每一项 $a_i\le n$。要满足 $a_i|a_{i-1}=n$。

题目分析

要使得 $a_i|a_{i-1}=n$,我们不妨先找找规律:

当 $n=14$ 时,可以构造出以下数据:

$a_1=6$

$a_2=10$

$a_3=12$

$a_4=14$

将其转化为 二进制

$0110$
$1010$
$1100$
$1110$

通过观察此数据,可以发现,构造出的数字的二进制存在规律,即将 $n$ 从末位开始将每个 $1$ 都去除一次,这样可以使得相邻两个数的异或值都为 $n$。

Code

#pragma GCC optimize(1, 2, 3, "Ofast", "inline")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
#define ONLINE_JUDGE
 #define MULTI_CASES
const int MaxN = 2e5+100;
const int INF = 1e9;
int T=1, N, M;
int a[MaxN];
int Atoi(string s,int radix)    //s是给定的radix进制字符串
{
	int ans=0;
	for(int i=0;i<s.size();i++)
	{
		char t=s[i];
		if(t>='0'&&t<='9') ans=ans*radix+t-'0';
		else ans=ans*radix+t-'a'+10;
	}
	return ans;
}
//n是待转换的十进制数,m是待转换成的进制数 
string intToA(int n,int m){
	string ans="";
	do{		 //使用do{}while()循环类型以防止输入为0的情况
		int t=n%m;
		if(t>=0&&t<=9)    
			ans+=(t+'0');
		else 
			ans+=(t+'a'-10);
		n/=m;
	}while(n);   
	reverse(ans.begin(),ans.end());
	return ans;    
}

inline void Solve()
{
	cin>>N;
//	char s1[MaxN];
	string s;
	s=intToA(N,2);
	
	M=1;
//	cout<<s<<endl;
	for(int i=0;i<s.size();i++){
		if(s[i]=='1'){
			M++;
		}
	}
	if(M==2){
		cout<<1<<endl<<N<<endl;
		return;
	}
	cout<<M<<endl;
	for(int i=0;i<s.size();i++){
		if(s[i]=='1'){
			string str=s;
			str[i]='0';
			cout<<Atoi(str,2)<<" ";
		}
	}
	cout<<N<<endl;
//	cout<<endl;
//	cout<<s<<endl;
}
signed main()
{
#ifndef ONLINE_JUDGE
	freopen(".in", "r", stdin);
	freopen(".out", "w", stdout);
#endif
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	
#ifdef MULTI_CASES
	cin >> T;
	while (T--)
#endif
		Solve();
	//fclose(stdin);
	//fclose(stdout);
	return 0;
}

本文采用 CC BY-NC 4.0 许可协议,转载请注明出处并保持非商业用途。