意思是给出四个参数,需要构造一个01串
a00表示构造的01串的子串为00的数量
a01表示构造的01串的子串为01的数量
a10表示构造的01串的子串为10的数量
a11表示构造的01串的子串为11的数量
譬如01010 a00=2 a01=3 a10=3 a11=1
输出四个参数严格等于给定参数的01串,不存在则输出Impossible。
题解:
这是道构造题,首先可以通过a00和a11计算出该串中0的个数和1的个数。
不难想到,由a00和a11可以确定0和1的数量,定义为c0和c1。
则一定满足
c0(c0−1)2==a00
c1(c1−1)2==a11
注意此处若0和1的个数都大于2那么个数唯一,若a00为0,那么有可能有1个0,也有可能没有0,遇到这种情况那么还需要判断a01和a10,若a01和a10都为0,那么0的个数为0,否则0的个数为1,判断1的个数时也一样。
判断完0和1的个数后,如果其中有一个个数为0,那么需要特判。
如果个数都不为0,且a01和a10个数满足要求是,此时就肯定存在01串,那么先将01串写成前半部分全是1,后半部分全是0,此时a01个数为0,然后对于后半部分的第一个0,如果向前与前面的1交换一次,那么a01个数加一,对每个0进行交换,直到a01个数满足要求。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1000000+10;
int s[maxn];
typedef long long ll;
int main()
{
ll a,b,c,d;
while(~scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&d))
{
memset(s,0,sizeof(s));
ll num0,num1;
if(d==0&&b==0&&c==0)
num1=0;
else num1=1;
if(a==0&&b==0&&c==0)
num0=0;
else num0=1;
while(num0*(num0-1)/2<a)
num0++;
if(num0*(num0-1)/2!=a)
{
puts("Impossible");
continue;
}
while(num1*(num1-1)/2<d)
num1++;
if(num1*(num1-1)/2!=d)
{
puts("Impossible");
continue;
}
if(num0*num1<b||num0*num1<c)
{
puts("Impossible");
continue;
}
if(num0*num1!=b+c)
{
puts("Impossible");
continue;
}
if(num1==0||num0==0)
{
if(num1)
for(int i=0;i<num1;i++) printf("1");
else if(num0)
{
for(int i=0;i<num0;i++) printf("0");
}
else
printf("0");
printf("\n");
continue;
}
for(int i=1;i<=num1;i++) s[i]=1;
int pos0=num1+1,pos1=1;
bool flag=false;
int tmp=b;
while(tmp>=num1)
{
swap(s[pos0],s[pos1]);
pos0++,pos1++;
tmp-=num1;
}
if(tmp>0)
swap(s[pos0],s[pos0-tmp]);
for(int i=1;i<=num1+num0;i++) printf("%d",s[i]);
printf("\n");
}
}