CF401C

扯在前面

本题的英文翻译很有意思,很符合CF大多题的故事风格,但是luogu的翻译更过于直白易懂

如果让我看英文故事做题我怕我都不知道该怎么下手


正文

题意

构造一个01序列,包含n个0,m个1要求不存在连续2个0,或3个1


什么意思呢,简单说就是,理想状态下我们能把所有0和1消耗完且消耗的最多的情况就是这样

假设有十个1
那么最多有
010101010101010101010
十一个0

最少有
11011011011011
四个0

因此我们可以得出两种无解的情况:

  • 0很多(1很少) 此时n>m+1 或m<n-1;
  • 0很少(1很多) 此时n<(m+2)/2 或m>2n+2;

那我们就判断出来,输出-1;


之后再想想怎么构造01序列:

根据测试,我们可以发现,同样的m和n可能会构造出不同的01序列(像本题的样例一,若输出011也是对的,因为评测机只统计0和1的个数而不是具体排列方式)

那我们就找规律,做法如下:

  1. 我们可以选择构造01和011序列来把总序列拼出来;
  2. 当m=2n时,我们就可以愉快的输出n个011,同理,当m=n时,我们也可以愉快的输出n个01;
  3. 如果情况并不是正好怎么办,因为无解的情况已经判断完,所以我们手中的情况保证有解,所以如果多了1就在总序列前面输出,如果少了1就从把后面的011换成01就好了

之后输出,代码如下

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;

int n,m,tot1,tot2,cnt;

int main(){
	scanf("%d%d",&n,&m);
	if(m>2*n+2){
		cout<<-1;
		return 0;
	}
	if(m<n-1){
	    cout<<-1;
	    return 0;
	}
	if(m==n*2+1){cout<<1;m--;}
	if(m==n*2+2){cout<<11;m-=2;}
	while(n){
		cout<<0;
		if(m!=0){
			if(m<n*2){cout<<1;m--;}
			else {cout<<11;m-=2;}
		}
		n--;
	}
	return 0;
}
谢谢观看
原文地址:https://www.cnblogs.com/KnightL/p/13935479.html