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. leetcode-WordLadder

    Word Ladder Total Accepted: 10243 Total Submissions: 58160My Submissions Given two words (start and  ...

  2. HDU-4041-Eliminate Witches! (11年北京网络赛!!)

    Eliminate Witches! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  3. Netty4具体解释二:开发第一个Netty应用程序

        既然是入门,那我们就在这里写一个简单的Demo,client发送一个字符串到server端,server端接收字符串后再发送回client. 2.1.配置开发环境 1.安装JDK 2.去官网下 ...

  4. Qt Creator 你必须要掌握的快捷操作

    多使用快捷键能显著提高工作效率,尽可能减少键盘,鼠标之间切换所浪费的时间.我这里列出个人认为非常重要必须掌握的 Qt Creator 快捷键.看你知道几个? . 1 .Ctrl(按住)+ Tab快速切 ...

  5. Struts2 ValueStack

    一.作用 可以作为一个数据中转站,用在前台和后台数据传递 二.生命周期 ValueStack的生命周期是随着request的创建而创建,随request的销毁而销毁. 三.结构 OgnlValueSt ...

  6. [总结]RTMP流媒体技术零基础学习方法

    本文主要总结一些我在学习RTMP流媒体技术过程中积累的经验.也为后来学习RTMP流媒体技术的人们一个参考.本文力图从简到难,循序渐进的介绍RTMP流媒体技术的方方面面,先从应用说起,逐步深化剖析相关工 ...

  7. 【转】iOS25彩票 幸运转盘

    原文 : http://www.it165.net/pro/html/201409/21216.html 最终效果图: 各个view的关系图: 背景圆盘(需穴ky"http://www.it ...

  8. qrcode-php生成二维码

    调用PHP QR Code非常简单,如下代码即可生成一张内容为"http://www.baidu.com"的二维码. include 'phpqrcode.php'; QRcode ...

  9. 挖潜无极限———数据挖掘技术与应用热点扫描[ZZ]

    “我们把世界看成数学,并且把你也看成数学”——用这句话来说明数据挖掘技术的复合性和应用的广泛性似乎再好不过.如今,虽然一些行业在应用这一技术上仍然缺乏足够的主动,但一个不能阻挡的趋势是:已经有越来越多 ...

  10. Lua-C交互函数

    lua_gettable(lua_State * , tableIndex) //获取表的在key位置的值 过程:tableIndex为表在栈的位置,例:-2为第二个位置 , 此时会弹(出)栈作为参数 ...