gym 101933J构造01串

题目链接:https://vjudge.net/problem/Gym-101933J
主要参考:https://www.cnblogs.com/wangzhebufangqi/p/11309965.html
https://blog.csdn.net/tianyizhicheng/article/details/83301634
题意:输入a,b,c,d,分别代表00、01、10、11的数量,让你构造出一个字符序列。
思路:可以根据组合公式推出0、1的个数分别为x、y。这里有一个结论:如果能够构造出来,那么x*y=b+c。好像是挺好理解的。先进行一系列的特判,再把0放入。接下来计算1的插入位置。假如有n个0,1的插入位置为p,那么增加的10数目为n-p,增加的01数目为p。

#include <bits/stdc++.h>
using namespace std;
long long solve(long long x)//根据组合公式可以得出方程组x*(x-1)=a
{
    x*=2;
    long long i=1;
    for(;; i++)
    {
        if(i*(i-1)>x)
            break;
    }
    i--;
    if(i*(i-1)==x)
        return i;
    return -1;
}
int main()
{
    long long a,b,c,d;
    scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
    if(!a&&!b&&!c&&!d)//如果全为0的情况
    {
        printf("0\n");
        return 0;
    }
    long long x=solve(a),y=solve(d);
    if(x==-1||y==-1)//没有解的情况
    {
        printf("impossible\n");
        return 0;
    }
    if(x==1&&y==1)//只有一个0一个1的情况
    {
        if(b&&c)
        {
            printf("impossible\n");
        }
        else if(b==1)
        {
            printf("01\n");
        }
        else if(c==1)
        {
            printf("10\n");
        }
        else if(b==0&&c==0)
        {
            printf("impossible\n");
        }
        else
        {
            printf("impossible\n");
        }
        return 0;
    }
    else if(x==1)//当输入a=0时,x才会=1 也就是说没有00 那么也就是说
    {            //x可以为0或者1 又因为没有10 01,x必须为0
        if(b==0&&c==0)
            x=0;
    }
    else if(y==1)
    {
        if(b==0&&c==0)
            y=0;
    }
    if(x*y!=b+c)
    {
        printf("impossible\n");
        return 0;
    }
    string s;
    for(int i=0; i<x; i++)//先把0放入
    {
        s+='0';
    }
    long long left=b;//还需要增加多少01
    while(y--)
    {
        long long e=min(left,x);//防止越界的情况
        s.insert(e,"1");
        left-=e;
    }
    cout<<s<<endl;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值