D. Recover the String
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
For each string s consisting of characters ‘0’ and ‘1’ one can define four integers a00, a01, a10 and a11, where axy is the number of subsequences of length 2 of the string s equal to the sequence {x, y}.
In these problem you are given four integers a00, a01, a10, a11 and have to find any non-empty string s that matches them, or determine that there is no such string. One can prove that if at least one answer exists, there exists an answer of length no more than 1 000 000.
Input
The only line of the input contains four non-negative integers a00, a01, a10 and a11. Each of them doesn’t exceed 109.
Output
If there exists a non-empty string that matches four integers from the input, print it in the only line of the output. Otherwise, print “Impossible”. The length of your answer must not exceed 1 000 000.
Examples
input
1 2 3 4
output
Impossible
input
1 2 2 1
output
0110
题意:给了 a00 a01 a10 a11四个数,构造一个01序列。a00表示满足pi==0,pj==0且j>i的二元组数量。其余3个同理。若无合法的序列输出Impossible。
做法:显然cnt0(cnt0-1)/2=a00,cnt1(cnt1-1)/2=a11。用二次方程求根公式求出cnt0和cnt1,若无根则无解。然后判断a01+a10==cnt0*cnt1是否成立,不成立则无解,成立则必有解。
几个坑点:对于0 0 0 0,0 0 0 x,x 0 0 0 单独判一下。最重要的是求根公式里的8a00(a11)会爆
int!!!尼玛啊!!!好好的上分场就这么gg了不服啊!!!改了秒过啊!!!
cnt0*cnt1就是所有01对(不分顺序)的个数。
构造的过程很自然,先把0全放在左边,这样所有01对都是(01)的形式,每把一个0从左边移到最右边就是(10)加了cnt1的个数。做一个带余除法,余数用1个0在所有的1中间微调即可。
举个例子具体一点说:
10 18 7 10
0000011111->0000111110->0001101110
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a00, a01, a10, a11;
int cnt0, cnt1;
int main()
{
scanf("%d%d%d%d", &a00, &a01, &a10, &a11);
if(!a00&&!a01&&!a10&&!a11){
printf("0\n");
return 0;
}
if(!a00&&!a01&&!a10)
{
cnt1=(sqrt(8*(ll)a11+1)+1)/2+0.000001;
if((ll)cnt1*(cnt1-1)/2!=a11){
printf("Impossible\n");
return 0;
}
for(int i=1;i<=cnt1;i++)printf("1");
printf("\n");
return 0;
}
if(!a11&&!a01&&!a10)
{
cnt0=(sqrt(8*(ll)a00+1)+1)/2+0.0000001;
if((ll)cnt0*(cnt0-1)/2!=a00){
printf("Impossible\n");
return 0;
}
for(int i=1;i<=cnt0;i++)printf("0");
printf("\n");
return 0;
}
cnt0=(sqrt(8*(ll)a00+1)+1)/2+0.0000001;
if((ll)cnt0*(cnt0-1)/2!=a00){
printf("Impossible\n");
return 0;
}
cnt1=(sqrt(8*(ll)a11+1)+1)/2+0.0000001;
if((ll)cnt1*(cnt1-1)/2!=a11){
printf("Impossible\n");
return 0;
}
//printf("%d %d\n", cnt0, cnt1);
if(ll(cnt1)*ll(cnt0)!=ll(a01)+ll(a10)){
printf("Impossible\n");
return 0;
}
int tot=a01+a10;
int pp=a01/cnt1;
int qq=a01-pp*cnt1;
for(int i=1;i<=pp;i++)printf("0");
for(int i=1;i<=cnt1-qq;i++)printf("1");
if(pp<cnt0)printf("0");
for(int i=1;i<=qq;i++)printf("1");
for(int i=1;i<=cnt0-pp-1;i++)printf("0");
printf("\n");
}
最近各种zz实习烦的一笔,搞得智商低下,还是要多做比赛挽回一点。cf打到1800停住了,也正常,div2abc上d1不现实(虽说手速犇能做到)。但是感觉突破也快到了,毕竟div2的d不难,只是由于各种zz原因(比如这次的爆int和之前的fst)跪了。预计3场以内上紫吧,但愿别打脸。