E - Checksum
ICPC训练赛的一道题,感觉还不错,难度不是很大。感觉考到了一个小小的思维。
题意:给出
n
n
n组数据,每组数据下包含两个整数
n
,
k
n,k
n,k,第二行输入一个长度为n的01串A,找到一个01串B长度为k,将A和B中1的个数相加得到D,将D转化成2进制,判断D与B是否一样,如果一样的话输出最小的B,否则输出None
思路:B的长度为0到k,那么B中1的个数为0到k个,因为A中1的个数是已知的,所以我们D的大小是差不多已知的,我们循环0到k可以算出来D的大小,再每次将D的大小写成2进制。
注意!这里有很重要一点,就是如何判断B中0和1的位置关系。只要我们这样写下去模拟几次就会发现,其实我们并不用关注B中的排列位置,当我们2进制下的D中1的个数和B中1的个数相同二者就是一样的,模拟几次就会发现这样的一个规律了。
注意有一点!我们一定要将D转化的二进制个数和B的长度一样,不然就不用考虑了,如果不够长我们可以加0来写二进制,因为不影响大小。
#include <bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define fi first
#define se second
#define PII pair<int,int>
using namespace std;
const int N = 1e5+5;
int a[N],b[N];
void solve ()
{
string ans="99999999999999";//定义一个很大的string,用于判断
int n,k;cin>>n>>k;
string s;cin>>s;int cnt=0;
for (int i=0;i<s.size();i++)
{
if (s[i]=='1') cnt++;
}
for (int i=0;i<=k;i++)
{
string t;
int now=cnt+i;
int sss=0;
while (now&&sss<k)//转化成二进制
{
t+=(now%2)+'0';
sss++;
now>>=1;
}
for (int i=t.size();i<k;i++)
t+="0";//如果长度不够就补0
reverse(t.begin(),t.end());//反转过来
int pos=count(t.begin(),t.end(),'1');
if (pos==i)
{
ans=min(ans,t);
}
}
if (ans=="99999999999999") cout<<"None"<<'\n';
else cout<<ans<<'\n';
}
signed main ()
{
IOS;
int T =1;
cin>>T;
while(T--) solve ();
return 0;
}