【CodeForces】708 B. Recover the String 数学构造
【题意】找到一个串s,满足其中子序列{0,0}{0,1}{1,0}{1,1}的数量分别满足给定的数a1~a4,或判断不存在。数字<=10^9,答案<=10^6。
【算法】数学构造
【题解】首先由a1和a4易得0的数量x0和1的数量x1。
容易发现01和10关系密切,令1的位置为b1...bx1,则:
{0,1} (b1-1)+(b2-2)+(b3-3)+...+(bx1-x1)=a2
{1,0} (x0-b1+1)+(x0-b2+1)+...+(x0-bx1+x1)=a3
两式相加,得x0*x1=a2+a3。
因此,只要满足表达式x0*x1=a2+a3,串就一定存在,此时只要随便构造b[]使得{0,1}数量符合,那么{1,0}数量就一定随之符合。
注意特殊处理0的情况。
#include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<queue> #include<stack> #include<set> #include<vector> #include<algorithm> #define ll long long #define lowbit(x) x&-x using namespace std; int read(){ char c;int s=0,t=1; while(!isdigit(c=getchar()))if(c=='-')t=-1; do{s=s*10+c-'0';}while(isdigit(c=getchar())); return s*t; } int min(int a,int b){return a<b?a:b;} int max(int a,int b){return a<b?b:a;} int ab(int x){return x>0?x:-x;} //int MO(int x){return x>=MOD?x-MOD:x;} //void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;} /*------------------------------------------------------------*/ const int inf=0x3f3f3f3f; int n,a1,a2,a3,a4,x0,x1,b[1000010],c[1000010]; void p(){printf("Impossible");exit(0);} int main(){ scanf("%d%d%d%d",&a1,&a2,&a3,&a4); for(int i=1000000;i>=1;i--){ if(1ll*i*(i-1)/2==a1)x0=i; if(1ll*i*(i-1)/2==a4)x1=i; } if(!x0||!x1)p(); if(a2+a3==0){ if(x0==1){ for(int i=1;i<=x1;i++)printf("1"); return 0; } if(x1==1){ for(int i=1;i<=x0;i++)printf("0"); return 0; } } if(x0*x1!=a2+a3)p(); for(int i=1;i<=x1;i++)b[i]=i; for(int i=x1;i>=1;i--){ if(a2>x0)b[i]=x0+i,a2-=x0;else{b[i]=a2+i;break;} } for(int i=1;i<=x1;i++)c[b[i]]=1; for(int i=1;i<=x1+x0;i++)printf("%d",c[i]); return 0; }