題目連結
CF1360H
解題思路
發現你可以十分高效的統計小於等於 \(x\) 的合法的數字數量。
並且你可以發現,當 \(x\) 遞增時,合法的數字數量是不遞減的,因此合法的數字數量是具有單調性的。
於是可以進行二分答案。
那麼如何進行 check 呢?我們先將不可選用的二進位制數字給轉化成數字,然後假設我們是找小於 \(x\) 可選用的數字數量,直接用 \(x + 1\) 再減去小於等於 \(x\) 的不可選用的數字數量即可。
因此單次 check 根據是 \(O(n)\) 的。
總時間複雜度為 \(O(n \log 2^m)\),非常優秀。
注意輸出的時候需要帶前導零補齊輸出。
參考程式碼
點選檢視程式碼
#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;
}