AIM Tech Round 3 (Div. 2) E. Connecting Universities 【构造】

00和11的个数可以推测出0和1的个数,设00为n个,0为m个,有n=(m-1)m/2。如果00和11的个数为0的话,如果有10和01的,那么0和1的个数为1。假设0为x个,1为y个,那么10和01的个数必要符合等于x y。最后构造答案,假设有一个x个0的字符串,那么我们去构造10的这种组合,只需要在字符串中插入1,然后统计一下这个1后面有几个0,如果刚好有符合题目个10组合,那么把1全部放在最后一个0的后面。这样子01会自动符合条件的。

/* ***********************************************
Author        :Maltub
Email         :xiang578@foxmail.com
Blog          :htttp://www.xiang578.com
************************************************ */

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
//#include <bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
using namespace std;
typedef vector<int> VI;
typedef long long ll;
const ll mod=1000000007;
const int N=1e6+10;
int a[N];
string s;
ll get(ll x)
{
    ll l=1,r=1e6,m,ret=-1;
    while(l<=r)
    {
        m=(l+r)/2;
        ll t=m*(m-1)/2;
        //printf("%lld %lld %lld\n",l,r,t);
        if(t>x)
        {
            r=m-1;
        }
        else if(t<x)
        {
            l=m+1;
        }
        else
        {
            return m;
            break;
        }
    }
    return -1;
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ll a0,a1,a2,a3,t0,t1;
    scanf("%lld%lld%lld%lld",&a0,&a1,&a2,&a3);
    if(a0+a1+a2+a3==0) printf("0\n");
    else
    {
        if(a0==0)
        {
            if(!a1&&!a2) t0=0;
            else t0=1;
        }
        else
        {
            t0=get(a0);
        }
        if(a3==0)
        {
            if(!a2&&!a1) t1=0;
            else t1=1;
        }
        else
        {
            t1=get(a3);
        }
        //printf("%lld %lld\n",t0,t1);
        if(t0==-1||t1==-1||t0*t1!=a1+a2)
        {
            puts("Impossible");
            return 0;
        }
        int b=(int)a1,n=(int)a1,t,m=(int)t1;
        int c1=(int)t1;
        int c0=(int)t0;
         memset(a,0,sizeof(a));
        for(int i=c0;i>=1;i--)
        {
            if(b<i) continue;
            t=b/i;b%=i;
            a[i]=t;
            n-=t*i;
            m-=t;
            //printf("%d %d %d\n",i,a[i],n);
            if(n==0) break;
        }
        a[0]=m;
        //printf("%d\n",a[0]);
        if(t0!=0)
        {
            for(int i=0; i<c0; i++)
            {
                //printf("%d %d\n",i,a[i]);
                for(int j=0; j<a[i]; j++)
                    printf("1");
                printf("0");
            }
            for(int j=0;j<a[c0];j++)
                printf("1");
        }
        else
        {
            for(int i=0;i<c1;i++)
                printf("1");
        }
        printf("\n");

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值