B. Circus
链接
[https://codeforces.com/problemset/problem/1138/B]
题意
给你两个字符串0,1那种,你是否可以选出一半的字符串,同时取。
使得当前第一个字符串的1的个数等于,剩下没选的第二个字符串的1的个数。
分析
首先我是真的傻,因为,我一直在哪里分类讨论,结果想了半天,一点都不行。
那么这个时候我们就看数据n<=5000,也就是可以n*n解决。怎么暴力呢?
这题就是你初中的数学功底的体现了。统计00,01,10,11的个数A,B,C,D;
我们假设选的00,01,10,11的个数为a,b,c,d;
a+b+c+d=n/2; A+B+C+D=n;
我们枚举a,那么根据题意需要满足
这题真的就是个数学啊,而且也反应我对复杂度不敏感,有时候可以暴力,就一定暴力,因为它不容易出错比较稳。
复杂度分析,这方面我还是菜了。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e3+10;
char s[N],t[N];
int main(){
int n;
while(~scanf("%d",&n)){
scanf("%s",s+1);
scanf("%s",t+1);
int a,b,c,d,A=0,B=0,D=0,C=0;
for(int i=1;i<=n;i++)
if(s[i]=='0'&&t[i]=='1')
B++;
else if(s[i]=='1'&&t[i]=='0')
C++;
else if(s[i]=='1'&&t[i]=='1')
D++;
A=n-(B+D+C);
//cout<<A<<' '<<B<<' '<<C<<' '<<D<<endl;
bool flag=0;
for(a=0;a<=A&&a<=n/2;a++)
{
d=B+D+a-n/2;
if(d>=0&&d<=D&&(a+d)<=n/2){
for(b=0;b<=B&&(a+b+d)<=n/2;b++){
c=n/2-(a+b+d);
if(c>=0&&c<=C){
flag=1; break;
}
}
}
if(flag) break;
}
if(!flag) puts("-1");
else {
//cout<<a<<' '<<b<<' '<<c<<' '<<d<<endl;
for(int i=1;i<=n;i++)
if(s[i]=='0'){
if(t[i]=='0'&&a){
printf("%d ",i);
a--;
}
if(t[i]=='1'&&b){
printf("%d ",i);
b--;
}
}
else{
if(t[i]=='0'&&c){
printf("%d ",i);
c--;
}
if(t[i]=='1'&&d){
printf("%d ",i);
d--;
}
}
puts("");
}
}
return 0;
}