B. Circus
theme:给定n个人,2≤n≤5000且n为奇数。,每个人都有两个属性c与a,c[i]==0代表第i个人没有属性c,为1代表有,a同理。先要把这n个人均分为两组,要求第1组中有属性c的人数与第二组中有属性a的人数相同,输出一种分法中第一组的人的编号。
solution:对于每个人的属性有四种情况:(1,1)、(1,0)、(0,1)、(0,0)。设每种情况的人数为a,b,c,n-a-b-c,这些都是可以统计出的。设第一组中这四种人的个数分别为x,y,z,n/2-x-y-z,则第二组中个数为a-x,b-y,c-z,n/2-a-b-c+x+y+z。条件为x+y=a-x+c-z化简得2x+y+z=a+b,所以是求三个未知数,那么遍历x,y即可,求出z检查范围。
#include<bits/stdc++.h>
#define far(i,t,n) for(int i=t;i<n;++i)
#define pk(x) push_back(x)
#define endl "\n"
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
char c[5005],a[5005];
vector<int>v[4],ans;
int main()
{
int n;
cin>>n;
scanf("%s%s",c,a);
far(i,0,n)
{
if(c[i]=='1'&&a[i]=='1')
v[0].pk(i);
else if(c[i]=='0'&&a[i]=='1')
v[1].pk(i);
else if(c[i]=='1'&&a[i]=='0')
v[2].pk(i);
else
v[3].pk(i);
}
int l[4];
far(i,0,4)
l[i]=v[i].size();
far(x,0,l[0]+1)
far(y,0,l[1]+1)
{
int z=l[0]+l[1]-2*x-y;
int m=n/2-x-y-z;
if(z>=0&&z<=l[2]&&m>=0&&m<=l[3])
{
far(i,0,x)
printf("%d ",v[0][i]+1);
far(i,0,y)
printf("%d ",v[1][i]+1);
far(i,0,z)
printf("%d ",v[2][i]+1);
far(i,0,m)
printf("%d ",v[3][i]+1);
puts("");
return 0;
}
}
cout<<-1<<endl;
}