Description

输入三个整数\(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\)。

Input

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

Output

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

Sample Input

7 6 9

Sample Output

10

HINT

\(a,b,c \le 2^{30}\)

自己难得看出来一道高维的\(dp\)题目:\(f[i][j][k][l][m]\)表示前\(i\)位二进制数中,\(a’\)用了\(j\)个1,\(b’\)用了\(k\)个\(1\),合成的\(c’\)在前\(i\)位中有\(l\)个\(1\)。

于是,根据二进制加法,我们可以得到\(dp\)方程:

\[f[i+1][j+1][k][l+1][0] = min(f[i+1][j+1][k][l+1][0],f[i][j][k][l][0] \mid (1 \ll i))
\]

\[f[i+1][j+1][k][l][1] = min(f[i+1][j+1][k][l][1],f[i][j][k][l][1])
\]

\[f[i+1][j][k+1][l+1][0] = min(f[i+1][j][k+1][l+1][0],f[i][j][k][l][0] \mid (1 \ll i))
\]

\[f[i+1][j][k+1][l][1] = min(f[i+1][j][k+1][l][1],f[i][j][k][l][1])
\]

\[f[i+1][j+1][k+1][l][1] = min(f[i+1][j+1][k+1][l][1],f[i][j][k][l][0])
\]

\[f[i+1][j+1][k+1][l+1][1] = min(f[i+1][j+1][k+1][l+1][1],f[i][j][k][l][1] \mid (1 \ll i))
\]

\[f[i+1][j][k][l+1][0] = min(f[i+1][j][k][l+1][0],f[i][j][k][l][1] \mid (1 \ll i))
\]

\[f[i+1][j][k][l][0] = min(f[i+1][j][k][l][0],f[i][j][k][l][0])
\]

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std; typedef long long ll;
#define maxn (35)
ll a,b,c,f[maxn][maxn][maxn][maxn][2];
int n,w1,w2,w3; inline void ready()
{
memset(f,0x7,sizeof(f));
f[0][0][0][0][0] = 0;
int cnt,i;
for (i = a,cnt = 0;i;i >>= 1,++cnt) if (i & 1) ++w1;
n = max(n,cnt);
for (i = b,cnt = 0;i;i >>= 1,++cnt) if (i & 1) ++w2;
n = max(n,cnt);
for (i = c,cnt = 0;i;i >>= 1,++cnt) if (i & 1) ++w3;
n = max(n,cnt);
} inline void dp()
{
for (int i = 0;i < n;++i)
for (int j = 0;j <= i&&j <= w1;++j)
for (int k = 0;k <= i&&k <= w2;++k)
for (int l = 0;l <= i&&l <= w3;++l)
{
if (j < w1)
{
if (l < w3) f[i+1][j+1][k][l+1][0] = min(f[i+1][j+1][k][l+1][0],f[i][j][k][l][0]|(1<<i));
f[i+1][j+1][k][l][1] = min(f[i+1][j+1][k][l][1],f[i][j][k][l][1]);
}
if (k < w2)
{
if (l < w3) f[i+1][j][k+1][l+1][0] = min(f[i+1][j][k+1][l+1][0],f[i][j][k][l][0]|(1<<i));
f[i+1][j][k+1][l][1] = min(f[i+1][j][k+1][l][1],f[i][j][k][l][1]);
}
if (j < w1&&k < w2)
{
f[i+1][j+1][k+1][l][1] = min(f[i+1][j+1][k+1][l][1],f[i][j][k][l][0]);
if (l < w3) f[i+1][j+1][k+1][l+1][1] = min(f[i+1][j+1][k+1][l+1][1],f[i][j][k][l][1]|(1<<i));
}
if (l < w3) f[i+1][j][k][l+1][0] = min(f[i+1][j][k][l+1][0],f[i][j][k][l][1]|(1<<i));
f[i+1][j][k][l][0] = min(f[i+1][j][k][l][0],f[i][j][k][l][0]);
}
} int main()
{
freopen("3107.in","r",stdin);
freopen("3107.out","w",stdout);
scanf("%lld %lld %lld",&a,&b,&c);
ready();
dp();
if (f[n][w1][w2][w3][0] > (1ll<<40)) printf("-1");
else printf("%lld",f[n][w1][w2][w3][0]);
fclose(stdin); fclose(stdout);
return 0;
}

BZOJ 3107 二进制a+b的更多相关文章

  1. BZOJ 3107 [cqoi2013]二进制a+b (DP)

    3107: [cqoi2013]二进制a+b Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 995  Solved: 444[Submit][Stat ...

  2. bzoj 1192 二进制

    原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1192 继续刷水题,二进制思想 //By BLADEVIL var x :longint; ...

  3. BZOJ 1531 二进制优化多重背包

    思路: 讲道理我应该写单调队列优化多重背包的 但是我不会啊 但是我现在! 还不会啊 我就写了个二进制优化的.. 过了 //By SiriusRen #include <cstdio> #i ...

  4. BZOJ.3425.[POI2013]Polarization(DP 多重背包 二进制优化)

    BZOJ 洛谷 最小可到达点对数自然是把一条路径上的边不断反向,也就是黑白染色后都由黑点指向白点.这样答案就是\(n-1\). 最大可到达点对数,容易想到找一个点\(a\),然后将其子树分为两部分\( ...

  5. [BZOJ 2989]数列(二进制分组+主席树)

    [BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...

  6. 题解 bzoj 4398福慧双修(二进制分组)

    二进制分组,算个小技巧 bzoj 4398福慧双修 给一张图,同一条边不同方向权值不同,一条边只能走一次,求从1号点出发再回到1号点的最短路 一开始没注意一条边只能走一次这个限制,打了个从一号点相邻节 ...

  7. [Bzoj 1192][HNOI2006]鬼谷子的钱袋(二进制优化多重背包)

    (人生第一篇bzoj题解有点激动 首先介绍一下题目: 看它题目那么长,其实意思就是给定一个数a,求将其拆分成n个数,通过这n个数可以表示出1~a中所有数的方案中,求最小的n. 您看懂了嘛?不懂咱来举个 ...

  8. [BZOJ 2165] 大楼 【DP + 倍增 + 二进制】

    题目链接:BZOJ - 2165 题目分析: 这道题我读了题之后就想不出来怎么做,题解也找不到,于是就请教了黄学长,黄学长立刻秒掉了这道题,然后我再看他的题解才写出来..Orz 使用 DP + 倍增 ...

  9. BZOJ 1192 鬼谷子的钱袋 (二进制思想)

    题解:鉴于二进制的思想来划分 #include <cstdio> int main(){ int n,d=0;scanf("%d",&n); while(1&l ...

随机推荐

  1. app启动其他应用

    因开发需要内包一个app,所以要启动一个app,这种操作 如果知道包名和类名 其实很简单 只需要将包名内嵌即可(一般情况 我们都可以解压或者反接拿到) 代码如下: Intent intent = ne ...

  2. 亲测linux6.4 安装

    1.bios下点击 u盘 启动进入(两个Flash1.0,都试试) 2.最关键的部分是,不如windows启动 没有linux界面. others(只是把这个修改一下名字为windows7) cent ...

  3. [转] JavaScript中的属性:如何遍历属性

    在JavaScript中,遍历一个对象的属性往往没有在其他语言中遍历一个哈希(有些语言称为字典)的键那么简单.这主要有两个方面的原因:一个是,JavaScript中的对象通常都处在某个原型链中,它会从 ...

  4. [转]Flex 布局教程:语法篇

    网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中 ...

  5. Java基础知识强化99:Java 常见异常及趣味解释

    常见 Java 异常解释:(译者注:非技术角度分析.阅读有风险,理解需谨慎:) 1. java.langjava.lang软件包是java语言的核心部分,它提供了java中的基础类. java.lan ...

  6. PhalGo-介绍

    PhalGo-介绍 phalgo是一个Go语言的一体化开发框架,主要用于API开发应为使用ECHO框架作为http服务web程序一样可以使用,牛顿曾经说过"如果我比别人看得远,那是因为我站在 ...

  7. 使用了hibernate时候乱码问题

    在配置文件的url地址最后加上characterEncoding=utf-8

  8. SQL server 如何附加、还原、分离、备份数据库文件

    No1 : 附加 No2 : 还原            一.(需要 .bak文件)首先建立一个数据库,数据库名称与你的.bak文件名要相同. 当然.这时候的这个数据库还是空的,需要还原回去数据.右键 ...

  9. CoreMotion(加速计)

    加速计的作用 用于检测设备的运动(比如摇晃) 加速计的经典应用场景 摇一摇 计步器 ********************************** Core Motion获取数据的两种方式 pu ...

  10. Linux命令:head命令详解

    概述:head命令用于显示文件文字区块 1.格式 head [参数][文件] 2.参数 -q 隐藏文件名 -v 显示文件名 -c<字节> 显示字节数 -n<行数> 显示的行数 ...