CF2250B题解
关键1:什么情况是非法的
分为两种情况:
1.n的数量为偶数时,1的数量: \(\frac{n}{2}\),0的数量:\(\frac{n}{2}\),能形成最多的连续块的数量是\(2*(\frac{n}{2}-1)=n-2\),限制条件为
\(n-2<k\)。
2.n的数量为奇数时,1和0的数量的绝对差不能超过1,假设1的数量比0多,设1:\(a+1\),0:\(a\),\(a+1+a=n\),
\(a=\frac{n-1}{2}\),1的数量:\(\frac{n+1}{2}\),0的数量:\(\frac{n-1}{2}\),能形成最多的连续块的数量是\(\frac{n+1}{2}-1+\frac{n-1}{2}-1=n-2\),限制条件也是\(n-2<k\)。
关键2:构造的方式
将整个字符串分为了连续串和交替串。先输出连续串,再输出101010...此类交替串。
细节1:连续串中1和0的数量
1和0的连续串中字符的数量一定要接近,连续串中1的数量:\(\lceil \frac{k}{2} \rceil\)(可以通过上下取整转换公式转换\(\lceil\frac{a}{b}\rceil=\lfloor\frac{a+b-1}{b}\rfloor\),\(\lceil \frac{k}{2} \rceil=\lfloor\frac{k+1}{2}\rfloor+\),0的数量取\(\lfloor \frac{k}{2} \rfloor\)(1和0相反也行)。为什么1和0的数量要接近,因为题目中要满足1和0的绝对差不能超过1,1或0数量不平衡可能会导致绝对差超过1。
细节2:要先输出连续串数量少的数字
错误代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<climits>
#include<queue>
#include<cstring>
#include<cstdio>
#include<string>
#include<unordered_map>
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 0x3f3f3f3f
#define YES cout<<"YES"<<"\n";
#define NO cout<<"NO"<<"\n";
using namespace std;
int main(){
IOS;
int t,n,k;
cin>>t;
while(t--){
cin>>n>>k;
if(n-2<k) {
cout<<-1<<"\n";
continue;
}
int cnt1=0,cnt2=0;
for(int i=0;i<(k+1)/2+1;i++){
cout<<1;
cnt1++;
}
for(int i=0;i<k/2+1;i++){
cout<<0;
cnt2++;
}
for(int i=0;i<n-cnt1-cnt2;i++){
if(cnt2!=0)cout<<(i%2==0?1:0);
else cout<<(i%2==1?1:0);
}
cout<<"\n";
}
}
例如看这段代码,先输出连续串最多的数字1,结果会导致n=偶数且k=奇数时错误。
例如:n=6,k=1时输出:110101,011010绝对差超过1显然是错误的。
证明:在n=偶数,k=奇数的情况下,设连续块1数量=A,0数量=B,A=B+1(因为k是奇数,所以1的连续块总是会比0多1),
1.交替串先从1开始输出
在连续串中1会比0一个
连续串1的长度\(=\lceil\frac{k}{2}\rceil+1\)(或\(\lfloor\frac{k+1}{2}\rfloor+1\)),连续串2的长度\(=\frac{k}{2}+1\),所以交替串长度\(L=n-(\lceil\frac{k}{2}\rceil+1)-(\lfloor\frac{k}{2}\rfloor+1)=n-k-2\)(n-2是偶数,k是奇数,所以L是奇数)
可以观察规律
L=3 101 1:2 0:1
L=5 10101 1:3 0:2
交替串1=\(\frac{L+1}{2}\) 2=\(\frac{L-1}{2}\)
那么1的总数量=\(A+\frac{L+1}{2}\) 2=\(B+\frac{L-1}{2}\),绝对差=\(A-B+1=2\)
所以先输出连续串数量多的是错误的。
AC代码
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<climits>
#include<queue>
#include<cstring>
#include<cstdio>
#include<string>
#include<unordered_map>
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 0x3f3f3f3f
#define YES cout<<"YES"<<"\n";
#define NO cout<<"NO"<<"\n";
using namespace std;
int main(){
IOS;
int t,n,k;
cin>>t;
while(t--){
cin>>n>>k;
if(n-2<k) {
cout<<-1<<"\n";
continue;
}
//分别记录1和2的数量
int cnt1=0,cnt2=0;
//连续块 0
for(int i=0;i<k/2+1;i++){
cout<<0;
cnt2++;
}
//连续块 1
for(int i=0;i<(k+1)/2+1;i++){
cout<<1;
cnt1++;
}
for(int i=0;i<n-cnt1-cnt2;i++){
if(cnt2!=0)cout<<(i%2==0?0:1);
else cout<<(i%2==1?0:1);
}
cout<<"\n";
}
}
有问题请指出。