J.Jumbled String-----Gym101933(关于构造类题)

Jumbled String

Time Limit: 1 Sec Memory Limit: 128 Mb

练习链接https://codeforces.com/gym/101933/problem/H

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:

the subsequence 00 occurs a times,

the subsequence 01 occurs b times,

the subsequence 10 occurs c times, and

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


题目大意是这样的,对于给定的4个数字代表00、01、10、11能够通过不同的删数出现的次数,然后请你构造出这个满足这样条件的01序列。
关于构造类的题目一般是很头痛的,但没有办法有人带榜。。。
对于第一个样例我们可以先观察观察,3次00串,4次01,2次10,1次11;
比如样例:01001,。
构造时我们要先选好起点进行序列的构建比如说我先选2次10作为起点,即我只需要在1后面补两个0就好了即100,接下来一次11,那么我们将1放在最后面的话就不影响之前的构造了于是一个1001就好了,third,4次01,由于之前是最后与最前的关系,我们只需要找最后的1有几(n)个且它们之前有几个0(m)就好了(01串的个数为n* m),然后再在前面补0,由于1之前有2个0,即已经有了2个01串,要在最前面补零,则只需补一个,因为后面有2个1,于是(01001就出来了)。但我们队是从01串开始构建的emmmm讲了一堆废话。。。
如果存在这个序列的话构建工作并不算非常困难,但关键是对于impssible的判断还是比较复杂的。
对于01001我们尝试着手动删一遍:规定为第一个位置到第五个位置的数
对于00:删125、245、235
对于01:删345、123、234、124
对于10:删124、145、135
对于11:删134
然后我们发现其实这是一个选数的问题,对于10串和01串先不做考虑。。。00串:C(x,2)=3,11串:C(y,2)=1;其中x,y分别代表着零的个数和一的个数,那么我们只需要判断是否存在一个整数x,y使得该组合数成立,即解方程—C(x,2)=x*(x-1)/2=a;
则,用求根公式:x=(1+sqrt(1+8a))/2,然后将x带入C中判断是否等于a,这样可以筛去一大部分的impossible。Second,特判,当没有00串、没有11串、没有01、没有10时的情况,

if(a == 0&&d == 0) {    //无00和11
		if(b == 1&&c == 0) {
			printf("01\n");
		} else if(c == 1&&b==0) {
			printf("10\n");
		} else printf("impossible\n");
		return 0;
	}
	if(b==0&&c==0) {     //无01和10
		if(a==0) {
			for(i=1; i<=y; i++) printf("1");
			printf("\n");
		} else if(d==0) {
			for(i=1; i<=x; i++) printf("0");
			printf("\n");
		} else printf("impossible\n");
		return 0;
	}

接下来还有一个特判,观察01是否匹配。。。

if(x*y!=b+c) {
		printf("impossible\n");
		return 0;
	}

0的个数和1的个数相乘为0和1的组合,同时b+c也同样是0和1的组合,两者相等才是存在解的。
以上条件全都满足了,即存在该序列时,我们开始构建了。我们可以先构建01串,
ling=b/y 先将前导零输出再输出1,(此时0和1的匹配为成对的,比如00000111),之后如果有余下的01串,则添加一个0,再在后面补1(此时的个数y-已经用掉的)最后再补零(此时为x-已经用掉的)。
详情请看代码:

#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
int main() {
	ll a,b,c,d;
	scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
	if(a==0&&b==0&&c==0&&d==0) {      //这种情况一定要特判!!!
		printf("0\n");
		return 0;
	}
	ll x,y,i;
	x = (1 + sqrt(1+8*a)) / 2;
	if(x*(x-1)/2 != a) {
		printf("impossible\n");
		return 0;
	}
	y = (1 + sqrt(1 + 8*d)) / 2;
	if(y*(y-1)/2 != d) {
		printf("impossible\n");
		return 0;
	}
	if(a == 0&&d == 0) {
		if(b == 1&&c == 0) {
			printf("01\n");
		} else if(c == 1&&b==0) {
			printf("10\n");
		} else printf("impossible\n");
		return 0;
	}
	if(b==0&&c==0) {
		if(a==0) {
			for(i=1; i<=y; i++) printf("1");
			printf("\n");
		} else if(d==0) {
			for(i=1; i<=x; i++) printf("0");
			printf("\n");
		} else printf("impossible\n");
		return 0;
	}
	if(x*y!=b+c) {
		printf("impossible\n");
		return 0;
	}
	ll ling,yi;
	ling = b / y;
	yi = b % y;
	for(i=1; i<=ling; i++) printf("0");
	for(i=1; i<=y-yi; i++) printf("1");
	if(ling!=x)printf("0");
	for(i=1; i<=yi; i++) printf("1");
	for(i=1; i<=x-ling-1; i++) printf("0");
	printf("\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值