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. Python安装scipy

    1.下载numpy+mkl 下载链接:http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy 2.下载scipy 下载链接:http://www.lfd.uc ...

  2. C# WinForm 判断窗体控件是否修改过

    本文转载:http://www.cnblogs.com/LinFx/archive/2011/12/23/2299895.html 1.自定义控件, 和接口 ) return IsModify(con ...

  3. qt中使用opencv处理图片 QImage 和 IplImage 相互之间转换问题

    在用opencv处理图片显示在qt label上的时候遇到不是问题 1. qt上要用qimage形式才干显示 IplImage转成 Qimage 彩色图像转换 IplImage  *fram; QIm ...

  4. 从高德 SDK 学习 Android 动态加载资源

    前不久跑去折腾高德 SDK 中的 HUD 功能,相信用过该功能的用户都知道 HUD 界面上的导航转向图标是动态变化的.从高德官方导航 API 文档中 AMapNaviGuide 类的描述可知,导航转向 ...

  5. Java web 文件下载

    /** * 下载文件 * @param msg */ public boolean printOutFile(String fileFullName,String fileName) { if (fi ...

  6. Android(java)学习笔记205:网易新闻RSS客户端应用编写逻辑过程

    1.我们的项目需求是编写一个新闻RSS浏览器,RSS(Really Simple Syndication)是一种描述和同步网站内容的格式,是使用最广泛的XML应用.RSS目前广泛用于网上新闻频道,bl ...

  7. 解决Chrome谷歌浏览器不支持CSS设置小于12px的文字

    在最新版的谷歌里.已经不在支持这个属性啦 谷歌浏览器Chrome是Webkit的内核,有一个 -webkit-text-size-adjust 的私有 CSS 属性,通过它即 可实现字体大小不随终端设 ...

  8. c#读取文件

    你平时是怎么读取文件的?使用流读取.是的没错,C#给我们提供了非常强大的类库(又一次吹捧了.NET一番), 里面封装了几乎所有我们可以想到的和我们没有想到的类,流是读取文件的一般手段,那么你真的会用它 ...

  9. memcached和mongodb 在windows下安装

    要在新机器上安装memcached和mongodb服务,折腾了一天,终于把这两个服务在windows下跑起来了. memcached主要参考http://www.rootop.org/pages/27 ...

  10. Oracle主键自动生成_表and存储过程

    -- Create table create table T_EB_SYS_DN_SEQUENCE_CONFIG ( sequence_id VARCHAR2(36) default sys_guid ...