博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AtCoder Regular Contest 100 E:Or Plus Max(DP+位运算)解题报告
阅读量:6105 次
发布时间:2019-06-21

本文共 1156 字,大约阅读时间需要 3 分钟。

这题对于我来说是真的难。。。

题目大意:言简意赅。2的N次方个数,存为Ai,令1≤K≤2的N次方−1,请你求出(i,j),使Ai+Aj最大,并且0<=i< j<=2的N次方-1且(i or j)≤K。输出Ai+Aj的最大值。


思路:这一题长得是真的不像DP。

这道题虽然言简意赅,但大部分都是为了严谨,我们最要注意的就是i|j<=k这句话。用膝盖想一下便知若i|j<=k,则i|j必定<=k+1。那么我们就可以设dp[k]为k下Ai+Aj的最大值,那么就有dp[k]=max(dp[k-1],不知道什么东西)。我们主要要思考的就是这个“不知道什么东西”。
那么这个“不知道什么东西”肯定是区别于k-1下的那些(i,j)的,也就是说是新的几对(i,j),根据样例或者自己证明等等方式可知若x|y=z,那么x和y都必定小于等于z。


口胡证明: 因为或运算在都是0的情况下才会是0,不可能把1变成0,只会把0变成1,所以数字只会变大不会变小


接上文思路:那么,也就是说新的这几对(i,j)里,i或j等于k(因为小于等于k的前面都有了嘛),因为不管顺序,我们就直接让i等于k。式子就变成了k|j=k,根据证明可知j小于等于k,我们可以通过更改1的位数为0来得到所有小于k的数。但在这里我选择了反过来思考:我们循环这几位和k,然后更改k中的这一位的1为0,得到小于k的j,运用两个数组更新与这时的k相对应的j的最大值就行了,我们得到的就是两个一一对应的数组,每一个k对应其最大的j。

我不怎么会写dp方程,大概就是dp[k]=max(dp[k-1],a[k]+maxa[j])
(萌新瑟瑟发抖)


AC程序

//库省略using namespace std;const int maxn=300005;int n,a[maxn];int sum1[maxn],sum2[maxn];int ans[maxn];void upday(int val,int pos){    if(val>sum1[pos])    {        sum2[pos]=sum1[pos];        sum1[pos]=val;    }    else    {        if(val>sum2[pos])        {            sum2[pos]=val;        }    }}int main(){    cin>>n;    for(int i=0;i<(1<
>a[i]; sum1[i]=a[i]; } for(int i=0;i

转载于:https://www.cnblogs.com/NightRaven/p/9333244.html

你可能感兴趣的文章
[转]无法安装MVC3,一直卡在vs10-kb2483190
查看>>
Codeforces 520B:Two Buttons(思维,好题)
查看>>
web框架-(二)Django基础
查看>>
Jenkins持续集成环境部署
查看>>
emoji等表情符号存mysql的方法
查看>>
Excel到R中的日期转换
查看>>
检查磁盘利用率并且定期发送告警邮件
查看>>
MWeb 1.4 新功能介绍二:静态博客功能增强
查看>>
linux文本模式和文本替换功能
查看>>
Windows SFTP 的安装
查看>>
摄像机与绕任意轴旋转
查看>>
rsync 服务器配置过程
查看>>
预处理、const与sizeof相关面试题
查看>>
爬虫豆瓣top250项目-开发文档
查看>>
Elasticsearch增删改查
查看>>
oracle归档日志增长过快处理方法
查看>>
有趣的数学书籍
查看>>
teamviewer 卸载干净
查看>>
多线程设计模式
查看>>
解读自定义UICollectionViewLayout--感动了我自己
查看>>