「杂题乱刷2」CF1360H

题目链接

CF1360H

解题思路

发现你可以十分高效的统计小于等于 x 的合法的数字数量。

并且你可以发现,当 x 递增时,合法的数字数量是不递减的,因此合法的数字数量是具有单调性的。

于是可以进行二分答案。

那么如何进行 check 呢?我们先将不可选用的二进制数字给转化成数字,然后假设我们是找小于 x 可选用的数字数量,直接用 x+1 再减去小于等于 x 的不可选用的数字数量即可。

因此单次 check 根据是 O(n) 的。

总时间复杂度为 O(nm),非常优秀。

注意输出的时候需要带前导零补齐输出。

参考代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define pii pair<ll,ll>
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
ll _t_;
void _clear(){}
ll L,R;
ll n,m;
ll a[110];
string s;
ll pw(ll x){
	return 1ll<<x;
}
ll f(string s)
{
	ll k=0,sum=0;
	reverse(s.begin(),s.end());
	for(auto i:s)
		sum+=pw(k++)*(i=='1');
	return sum;
}
bool check(ll x)
{
	ll sum=x+1; // 注意 0 
	forl(i,1,n)
		if(a[i]<=x)
			sum--;
///	if(x==4)
//		cout<<"???"<<sum<<endl;
	return sum<((pw(m)-n+1)/2);
}
void print(ll x)
{
	if(x==0)
	{
		forl(i,1,m)
			cout<<0;
		cout<<endl;
		return ;
	}
	string s="";
	while(x)
		s+=x%2+'0',x/=2;
	ll sz=s.size();
	forl(i,1,m-sz)
		s+='0';
	reverse(s.begin(),s.end());
	cout<<s<<endl;
}
void solve()
{
	_clear();
	cin>>n>>m;
	L=0,R=pw(m)-1;
	forl(i,1,n)
		cin>>s,a[i]=f(s);
	sort(a+1,a+1+n);
	while(L<R)
	{
		ll Mid=(L+R)/2;
		if(check(Mid))
			L=Mid+1;
		else
			R=Mid;
	}
	print(L);
//	cout<<L<<endl;
}
int main()
{
	IOS;
	_t_=1;
	cin>>_t_;
	while(_t_--)
		solve();
	QwQ;
}
posted @   wangmarui  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示