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 }