列表

详情


NC19926. [CQOI2013]二进制A+B

描述

输入三个整数a, b, c,把它们写成无前导0的二进制整数。比如a=7, b=6, c=9,写成二进制为a=111, b=110, c=1001。接下来以位数最多的为基准,其他整数在前面添加前导0,使得a, b, c拥有相同的位数。比如在刚才的例子中,添加完前导0后为a=0111, b=0110, c=1001。最后,把a, b, c的各位进行重排,得到a’, b’, c’,使得a’+b’=c’。比如在刚才的例子中,可以这样重排:a’=0111, b’=0011, c’=1010。 
你的任务是让c’最小。如果无解,输出-1。  

输入描述

输入仅一行,包含三个整数a, b, c。

输出描述

输出仅一行,为c’的最小值。

示例1

输入:

7 6 9

输出:

10

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 3ms, 内存消耗: 604K, 提交时间: 2019-09-26 16:53:35

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int INF=0x7f7f7f7f;
int L;

int check(int x)
{
    int ans=0,i=0;
    for(;i<31;++i)
        if(x&(1<<i))
            ++ans,L=max(i+1,L);
    return ans;
}

int lenz(ll x)
{
    for(int i=61;i>=0;--i)
        if(x&(1ll<<i)) return i+1;
    return 0;
}

int main()
{
    // freopen(".in", "r", stdin);
    // freopen(".out", "w", stdout);
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    a=check(a),b=check(b),c=check(c);
    if(a<b) swap(a,b);
    if(c>a+b) puts("-1");
    else if(c==a+b)
        printf("%d\n",(1<<c)-1);
    else
    {
        int d=a+b-c;
        ll ans=0;
        // debug2(a,b);
        // debug2(c,d);
        if(d>=a)
        {
            ++ans;
            for(int i=0;i<2*d-a-b;++i) ans<<=1;
            for(int i=0;i<a+b-d-1;++i) ans<<=1,++ans;
            ans<<=1;
        } else if(d>=b)
        {
            ++ans;
            for(int i=0;i<d-b;++i) ans<<=1;
            for(int i=0;i<b-1;++i) ans<<=1,++ans;
            ans<<=1;
            for(int i=0;i<a-d;++i) ans<<=1,++ans;
        } else
        {
            for(int i=0;i<d;++i) ans<<=1,++ans;
            ans<<=1;
            for(int i=0;i<a+b-2*d;++i) ans<<=1,++ans;
        }
        // debug2(L,ans);
        if(lenz(ans)<=L) printf("%lld\n",ans);
        else puts("-1");
    }
    return 0;
}

/*==================================================================
added at 2019-09-26 15:51:55 P4574
第一次做自己推了一个60^4的dp公式,后来发现不能把a和b的1混起来用
所以还是换构造的方法重新做一遍
没有考虑到d>=a的那个情况
==================================================================*/

Python3(3.9) 解法, 执行用时: 41ms, 内存消耗: 6868K, 提交时间: 2021-05-07 19:34:32

def bin_count(x):
    bin_n = 0
    one_n = 0
    while x > 0:
        if (x & 1) == 1:
            one_n += 1
        bin_n += 1
        x >>= 1
    return bin_n, one_n

def solve(a, b, c):
    an, a1 = bin_count(a)
    bn, b1 = bin_count(b)
    cn, c1 = bin_count(c)
    if a1 < b1:
        bn, an = an, bn
        b1, a1 = a1, b1

    ans = -1
    if c1 == 0:
        if a1 + b1 == 0:
            ans = 0
    elif a1 + b1 == c1:
        ans = 0
        while c1 > 0:
            ans = (ans << 1) | 1
            c1 -= 1
    elif a1 + b1 > c1:
        k = a1 + b1 - c1
        t1 = min(k - 1, a1 - 1)
        t2 = k - 1 - t1
        y = min(a1 - t1 - 1, t2) + min(b1 - t2 - 1, t1)
        x = k - 1 - y
        z = a1 + b1 - y - k - 1
        if x + y + z + 2 <= max(an, bn, cn):
            ans = 1
            for i in range(x):
                ans <<= 1
            for i in range(y):
                ans = (ans << 1) | 1
            ans <<= 1
            for i in range(z):
                ans = (ans << 1) | 1

    print(ans)


if __name__ == '__main__':
    a, b, c = map(int, input().split())
    solve(a, b, c)

C++11(clang++ 3.9) 解法, 执行用时: 4ms, 内存消耗: 504K, 提交时间: 2020-02-14 16:06:20

#include<cstdio> 
#include<iostream> 
using namespace std; 
int calc(int x){ 
    int t=0; for (; x; x>>=1) t++; return t;  
}
int getit(int x){ 
    int t=0; for (; x; x^=x&-x) t++; return t; 
}
int main(){
    int a,b,c; scanf("%d%d%d",&a,&b,&c); 
    int len=max(max(calc(a),calc(b)),calc(c)),ans; 
    a=getit(a); b=getit(b); c=getit(c);  
    if (a>b) swap(a,b); 
    if (c<=a) ans=(1<<(a+b-c))|((1<<c)-2); 
    else if (c<=b) ans=((1<<b)|((1<<c)-1))^(1<<(c-a)); 
    else if (c<=a+b) ans=((1<<(c+1))-1)^(1<<(c+c-a-b)); 
    else {puts("-1"); return 0;  } 
    printf("%d\n",(calc(ans)<=len)?ans:-1); 
    return 0; 
}

上一题