CSU 2258 思维+构造

博客围绕能否构造一个01序列展开,该序列需满足有a个00、b个01、c个10、d个11。介绍了解题思路,先根据公式解得0和1的数量x和y,判断给定的a、b、c、d是否满足特定条件,若满足则给出构造01序列的方法。

http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=2258

Description

Recall that a subsequence of a string is any string obtained by removing some subset of characters from the string, for instance "string", "sing", "i" and "sg" are all subsequences of "string". If the same subsequence can be obtained in exactly t different ways, by removing different subsets of characters, we say that the subsequence occurs t times.

Jingfei wants to create a nonempty bit string that has the following properties:

  1. the subsequence 00 occurs a times,

  2. the subsequence 01 occurs b times,

  3. the subsequence 10 occurs c times, and

  4. the subsequence 11 occurs d times.

However, Jingfei does not know how to create such a string -- or whether it is even possible. Could you help her?

Input

he input consists of a single line with four integers a, b, c, and d (0 ≤ a, b, c, d ≤ 109​).

Output

Output a bit string that satisfies the given requirements. If there are several solutions, output any one of them. If there are no solutions, output "impossible".

Sample Input

3 4 2 1
---------------------
5 0 0 5

Sample Output

01001
---------------------
impossible

Hint

Source

ncpc2018

题目大意:问你能否构造一个01序列,满足有a个00、b个01、c个10、d个11。(不要求连续 任意选择可得到即可)

思路:设有x个0,y个1,则a=x*(x-1)/2,(从x个0里面任选两个)同理得d=y*(y-1)/2,由此我们可解得x和y的值,(注意 当a=0或d=0时解出来的x和y不一定正确 因此要加上特判)现在我们知道有x个0和y个1了,假设cal(v)=v*(v-1)/2,那么给定的a、b、c、d应该满足:cal(x+y)-cal(x)-cal(y)=b+c,(即从x+y个元素中任选两个 除去全选1和全选0的情况 应该等于01 和10的数量之和)否则是无解的;那在满足的情况下如何构造01序列呢?我们考虑先一直放0,那么每放一个0对01的贡献就是y,因为后面还要放y个1,因此此时最多放b/y个0,那么01的贡献还差b%y个,我们令rest=b%y,放入y-rest个1,此时若rest=0,则继续放1,否则放入1个0,使01的数量满足题意然后继续把1放完,最后把剩下的0填上去即可。(这题自己做的时候好蠢 感觉x和y求错了然后WA到自闭)

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define EPS 1e-8
using namespace std;
typedef long long ll;

ll a,b,c,d;
ll x,y;

inline ll cal(ll v)
{
	return v*(v-1)/2;
}

inline ll Find(ll v)
{
	v*=2;
	ll i;
	for(i=1;;i++)
		if(i*(i-1)>v)
			break;
	--i;
	if(i*(i-1)==v)
		return i;
	return -1;
}

int main()
{
	scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
	if(a==0&&b==0&&c==0&&d==0)
	{
		printf("0\n");
		return 0;
	}
	x=Find(a);
	y=Find(d);
	if(x==-1||y==-1)
	{
		printf("impossible\n");
		return 0;
	}
	if(a==0&&d==0)
	{
		if(b==1&&c==0)
			printf("01\n");
		else if(b==0&&c==1)
			printf("10\n");
		else
			printf("impossible\n");
		return 0;
	}
	if(b==0&&c==0)
	{
		if(a==0)
		{
			for(ll i=1;i<=y;i++)
				putchar('1');
			putchar('\n');
		}
		else if(d==0)
		{
			for(ll i=1;i<=x;i++)
				putchar('0');
			putchar('\n');
		}
		else
			printf("impossible\n");
		return 0;
	}
	if(cal(x+y)-cal(x)-cal(y)!=b+c)
		printf("impossible\n");
	else
	{
		 ll temp=b/y;
		 ll rest=b%y;
		 for(ll i=1;i<=temp;i++)
			putchar('0');
		 for(ll i=1;i<=y-rest;i++)
			putchar('1');
		 if(rest!=0)
		 {
			putchar('0');
			++temp;
		 }
		 for(ll i=1;i<=rest;i++)
			putchar('1');
		 for(ll i=temp+1;i<=x;i++)
			putchar('0');
		 putchar('\n');
	}
	return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值