codeforces 709D Recover the String (构造+模拟)

题目原文:

For each strings consisting of characters '0' and '1' one can define four integersa00,a01,a10 and a11, where axy is the number of subsequences of length2 of the strings equal to the sequence{x, y}.

In these problem you are given four integersa00,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 than1 000 000.

Input

The only line of the input contains four non-negative integersa00,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.


解题思路:根据题意可知可以借助00,11的数量来计算出序列中 0 和 1 的个数。这两个值必须是(n-1)*n/2这种格式的数。明确0和1的数目后再来匹配01的数目和10的数目。我们先假设所有的1位于一起。考虑如果让01,10的数目同时合法。只有放置在所有1两侧的0,对彼此的数目不产生影响。

可以证明的是如果这个串是可以得到的,那么最多只有1个0插在所有的1之间就可以得到答案。

设1的个数为k  设 b = m*k + x   c = n*k + y  (带余除法)如果有满足题意的解则  k |b + c(有整除关系)  // 因为b+c 等于 0的个数×1的个数。

那么只需要在1之间插入一个0,保证这个0前面有x个1就可以了~

考虑这么一组数据 3 5 4 3

可以知道这组数据里面有三个1,三个0。我们先将三个1放置在一起。然后考虑10,01.

  1. 111
  2. 0111       //01数目多于1的数目往前放置0
  3. 01101     //为了凑齐01的数目需要往1之间插入0
  4. 011010   //把剩下的0放在后面,如果满足条件输出答案

AC代码:
/*
    @Author: wchhlbt
    @Date:   2017/2/23
*/
#include <bits/stdc++.h>
#define Fori(x) for(int i=0;i<x;i++)
#define Forj(x) for(int j=0;j<x;j++)
#define maxn 100005
#define inf 0x3f3f3f3f
#define ONES(x) __builtin_popcount(x)
using namespace std;

typedef long long ll ;
const double eps =1e-8;
const int mod =  20071027 ;
typedef pair<int, int> P;
const double PI = acos(-1.0);
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};

int ans;
int zero,one;
int pos[maxn];
int main()
{
    //freopen("test.txt","r",stdin);
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    int a,b,c,d;
    cin>>a>>b>>c>>d;
    if((a+b+c+d)==0){
        cout << 0 << endl;
        return 0;
    }
    for(ll i = 1; i<=1e5; i++){
        if((i-1)*i/2==a)
            zero = i;
        if((i-1)*i/2==d)
            one = i;
    }
    if((c+b)==0){
        if(a==0)
        {
            if(d==1)    cout << 11 ;
            else if(one==0){
                cout << "Impossible" << endl;
                return 0;
            }
            else
                for(int i = 0; i<one; i++)
                    cout << 1 ;
            cout << endl;
        }
        else if(d==0)
        {
            if(a==1)    cout << "00";
            else if(zero==0){
                cout << "Impossible" << endl;
                return 0;
            }
            else
                for(int i = 0; i<zero; i++)
                    cout << 0 ;
            cout << endl;
        }
        else
            cout << "Impossible" << endl;
        return 0;
    }

    int i;
    for(i = 1; i<=zero; i++)
    {
        if(b==0)
            break;
        if(b>=one){
            b -= one;
        }
        else{
            pos[i] = (one-b);
            c -=(one-b);
            b = 0;
        }
    }
    for(int j = i; j<=zero; j++){
        if(c==0)    break;
        pos[j] = one;
        c -= one;
    }
    if(b!=0 || c!=0 || (zero+one)==0)
    {
        cout << "Impossible" << endl;
        return 0;
    }
    for(int k = 1; k<=zero; k++)
    {
        for(int j = pos[k-1]; j<pos[k]; j++){
            cout << 1;
            one--;
        }
        cout << 0;
    }
    while(one--)  cout << 1;
    cout << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值