Recover the String

Recover the String

题目链接:http://codeforces.com/contest/709/problem/D

构造

这题乍一看很难构造,但是如果知道了整个字符串中'0'和'1'的个数n0和n1,就很好构造了:

1.将整个字符串填满'1',在所有的1右边填x个'0',那么'10'就有x*n1个了,一直填到还需要'10'的个数t1小于n1个;

2.再从右边数n1-t1个'1'并在它前面添加一个'0';

3.删去多余的'1'.

如此看来,构造并不困难,难的是判断何时Impossible.我们可以看到a1和a4必须是(1+n)*n/2的形式,而a2+a3肯定等于n0*n1(对于每一个'1',若左边有x个'0',那么右边有n0-x个'0')。但是这样直接交还会WA,还有一种情况没有考虑:只有'1'或只有'0'的情况,这种情况特判就好啦。

代码如下:

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 int a,b,c,d;
 5 char s[1000005];
 6 int main(void){
 7     scanf("%d%d%d%d",&a,&b,&c,&d);
 8     if(a+b+c+d==0){
 9         printf("1\n");
10         return 0;
11     }
12     int n0=(int)sqrt(2*a)+1;
13     if(n0*(n0-1)/2!=a){
14         printf("Impossible\n");
15         return 0;
16     }
17     int n1=(int)sqrt(2*d)+1;
18     if(n1*(n1-1)/2!=d){
19         printf("Impossible\n");
20         return 0;
21     }
22     if(n0+n1>1000000){
23         printf("Impossible\n");
24         return 0;
25     }
26     if(c+b+d==0){
27         for(int i=0;i<n0;++i)
28             printf("0");
29         printf("\n");
30         return 0;
31     }else if(a+b+c==0){
32         for(int i=0;i<n1;++i)
33             printf("1");
34         printf("\n");
35         return 0;
36     }
37     if((c+b)!=n0*n1){
38         printf("Impossible\n");
39         return 0;
40     }
41     for(int i=0;i<n0+n1;++i)
42         s[i]='1';
43     int t=c/n1;
44     for(int i=0;i<t;i++)
45         s[n0+n1-1-i]='0';
46     int t1=c-t*n1;
47     int k=0,i;
48     for(i=n0+n1-1;i>=0;--i){
49         if(k==n1-t1){
50             s[i]='0';
51             break;
52         }
53         if(s[i]=='1')k++;
54     }
55     for(;i>=0;--i){
56         if(s[i]=='1')k++;
57         if(k>n1)s[i]='0';
58     }
59     printf("%s\n",s);
60 }

 

posted @ 2016-08-25 13:44  barriery  阅读(255)  评论(0编辑  收藏  举报