noi.ac309 Mas的童年
题面
题目描述
\(Mas\)完成了一天的工作,走在回家的路上,看着路边的景色,他想起来自己的童年。
许许多多的记忆交错,丝丝缕缕的牵扯着\(Mas\)。
在回忆的深处,\(Mas\)想起来了一个常常在幼儿园玩的游戏。
有\(n\)个小朋友一起排成一排,然后小朋友们会一起开始跳舞。
聪明的\(Mas\)发现,每个小朋友都有自己的高兴程度,对于第\(i\)个小朋友,他的高兴程度是\(ai\)。
当一排高兴程度分别为\(b_1,b_2,…,b_k\)的\(k\)个小朋友跳舞的时候,他们会产生\(b1 \otimes b2 \otimes ⋯\otimes bk\)的愉悦值。
但是\(Mas\)觉得不够尽兴,于是他决定让小朋友们从某个位置分开,让原本一排的队伍分成两排,从而使两排新队伍的愉悦值加起来最大,当然,是有可能不分成两排的。
具体的,对于一排kk个小朋友,他们的高兴程度分别是\(b_1,b_2,…,b_k\),\(Mas\)会找到位置\(i\in [0,k),使得(b1\otimes ⋯\otimes bi)+(bi+1\otimes ⋯\otimes bk)\)最大。
回想起这个游戏的\(Mas\)决定再来玩一下这个游戏,于是他想起来了某一天排成一排的\(n\)个小朋友的高兴程度\(a1,a2,…,an\)对于\(i=1..n\),\(Mas\)希望求出前\(i\)个小朋友排成的队伍中通过拆分成两个队伍能够得到的最大愉悦值的和是多少。
输入
第一行一个正整数\(n\)表示小朋友的数量。
第二行\(n\)个整数,表示\(a_{1..n}\)。
输出
一行\(n\)个整数表示答案。
思路
读完拉么长的题面。发现他其实就是对于每个位置要求这个东西
\]
其中\(S_i\)表示前\(i\)个元素的异或和。
然后根据\(a+b = a\otimes b + (a \& b) \times 2\)
这个证明的话很显然:因为异或相当于不进位的加法。用\(\&\)可以求出需要进位的位置。然后乘二在相加就可以啦。
这样我们就可以把要求的式子变成这个样子
\]
\]
因为\(S_i\)是确定的,只要让\(S_i \otimes S_j \& S_j\)最大就行了。
然后我们按位思考。对于二进制下的第\(k\)位。如果\(S_i\)的这一位为\(1\),那么不管\(S_j\)这一位是什么,肯定都无法将答案的这一位变成\(1\)。
所以我们就想要让\(S_i\)为\(0\)的那些位置尽可能变成\(1\)。
对于每个\(S_j\),我们将他和他的子集标记一下。然后贪心的从高位到低位将\(S_i\)为\(0\)的位置变为\(1\).
并且查看当前的答案是不是之前标记过。
具体看代码吧
代码
/*
* @Author: wxyww
* @Date: 2019-03-30 08:10:10
* @Last Modified time: 2019-03-31 08:31:43
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 2000000 + 100;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int s[N];
bool vis[N];
void ins(int x) {
if(vis[x]) return;
vis[x] = true;
for(int i = 0;i <= 20;++i) {
if((x >> i) & 1) ins(x - (1 << i));
}
}
int solve(int x) {
int ret = 0;
int k = x ^ ((1 << 21) - 1);
for(int i = 20;i >= 0;--i)
if(((k >> i) & 1) && vis[(ret + (1 << i))])
ret += (1 << i);
return ret;
}
int main() {
int n = read();
for(int i = 1;i <= n;++i) s[i] = s[i - 1] ^ read();
vis[0] = true;
for(int i = 1;i <= n;++i) {
printf("%d ",solve(s[i]) * 2 + s[i]);
ins(s[i]);
}
return 0;
}
noi.ac309 Mas的童年的更多相关文章
- 【noi.ac】#309. Mas的童年
#309. Mas的童年 链接 分析: 求$max \{sj + (s_i \oplus s_j)\}$ 因为$a + b = a \oplus b + (a \& b) \times 2$ ...
- noi.ac#309 Mas的童年(子集乱搞)
题意 题目链接 Sol 记\(s_i\)表示前\(i\)个数的前缀异或和,我们每次相当于要找一个\(j\)满足\(0 < j < i\)且\((s_i \oplus s_j) + s_j\ ...
- Noi.ac #309. Mas的童年(贪心)
/* 用所谓的加法拆分操作得到 x + y = (x ^ y) + 2 * (x & y) 那么我们这两段异或相当于前缀和 + 2 * 分段使左右两块&最大 记当前前缀异或和为S, 那 ...
- [NOI.AC省选模拟赛3.30] Mas的童年 [二进制乱搞]
题面 传送门 思路 这题其实蛮好想的......就是我考试的时候zz了,一直没有想到标记过的可以不再标记,总复杂度是$O(n)$ 首先我们求个前缀和,那么$ans_i=max(pre[j]+pre[i ...
- # NOI.AC省选赛 第五场T1 子集,与&最大值
NOI.AC省选赛 第五场T1 A. Mas的童年 题目链接 http://noi.ac/problem/309 思路 0x00 \(n^2\)的暴力挺简单的. ans=max(ans,xor[j-1 ...
- NOI2019 SX 模拟赛 no.5
Mas 的童年 题目描述:不知道传送门有没有用? 反正就是对于每个前缀序列求一个断点,使得断点左右两个区间的 分别的异或和 的和最大 分析 jzoj 原题? 但是我 TM 代码没存账号也过期了啊! 然 ...
- NOI2019省选模拟赛 第五场
爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...
- 从一道NOI练习题说递推和递归
一.递推: 所谓递推,简单理解就是推导数列的通项公式.先举一个简单的例子(另一个NOI练习题,但不是这次要解的问题): 楼梯有n(100 > n > 0)阶台阶,上楼时可以一步上1阶,也可 ...
- NOI 动态规划题集
noi 1996 登山 noi 8780 拦截导弹 noi 4977 怪盗基德的滑翔翼 noi 6045 开餐馆 noi 2718 移动路线 noi 2728 摘花生 noi 2985 数字组合 no ...
随机推荐
- 2018/1.6 Javascript 继承和克隆
这种写法不是对象克隆,就是把obj的内存地址赋给obj2 通过 for in 克隆 不管公有还是私有的都克隆成私有的. js提供了一个克隆方法 objct.create() var obj2=obje ...
- 学习笔记—JVM
JVM结构 JVM总体结构图 类加载子系统与方法区: 类加载子系统负责从文件系统和网络中加载Class信息,加载的类信息存放于一块称为方法区的内存空间. 除了类信息外,方法区中还可能会存放运行时常量池 ...
- off-canvas:抽屉式页面布局的纯css实现
Off-canvas即抽屉式的侧边导航栏布局,导航栏在大尺寸屏幕的时候可以设置无需隐藏,小尺寸屏幕的时候自动隐藏,并出现.off-canvas-toggle用以打开导航栏,打开导航栏的状态下可以点击非 ...
- Python-函数小结
原文出处,如有侵权,请联系删除. 用户自定义.py文件 如果你已经把my_abs()的函数定义保存为abstest.py文件了,那么,可以在该文件的当前目录下启动Python解释器,用from abs ...
- datatable动态列处理,重绘表格(敲黑板,划重点!!!我肝了一天半才彻底弄懂这个东西,TAT)
datatable动态列处理,重绘表格 前言:至于动态列的绘画,我前面博客已经写过了,就是动态列的配置问题,不懂的去我博客看下,今天要写的呢,就是你已经写了一个动态列在datatable,现在你想重新 ...
- JMeter 接口测试-if控制器
JMeter 接口测试-if控制器 使用场景: 当业务场景是用户登录才能支付操作, 不登录点击支付, 页面会跳转到登录页面. 对于接口也是这样, 一个接口需要执行前, 需要有前提条件, 比如0状态 ...
- Linux(Manjaro) -Docker 安装及基本配置
Linux(Manjaro) -Docker 安装及基本配置 基本安装 # Pacman 安装 Docker sudo pacman -S docker # 启动docker服务 sudo syste ...
- JAVA EE获取浏览器和操作系统信息
一.原理说明: 1. 浏览器访问服务端时,Http请求头上会带上客户端一些信息,可通过"user-agent"获取. //java获取方法如下,其他语言也有自己获取方法 Stri ...
- RC4
RC4(Rivest Cipher 4)是一种流加密算法,密钥长度可变.并且因为加解密时使用的密钥相同,所以也为对称加密.加密过程和解密过程仅明密文的区别. 主要分为初始化 s 盒和伪随机密码生成组成 ...
- 用jenkins创建节点
原料:(1)jre下载链接:https://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html ( ...