UOJ#370. 【UR #17】滑稽树上滑稽果 动态规划
原文链接www.cnblogs.com/zhouzhendong/p/UOJ370.html
题解
首先易知答案肯定是一条链,因为挂在链的最下面肯定比挂在其他节点上赚。
问题被转化成了从一个集合中不断选数加入到当前序列尾端,使得序列的所有前缀 AND 之和最小。
我们发现,假如加入一个数后可以使序列的 AND 值变小,那么必然不会去加一个使 AND 值不变的。
假设 $v = a_1\ {\rm and} \ a_2 \ {\rm and}\ \cdots \ {\rm and}\ a_n$,先使 $a'_i = a_i\ {\rm XOR}\ v$ ,然后对于 a' 来求答案,最后答案加上 $n\cdot v$ 。
由于在序列的 AND 值变成 0 之前,每次都会使 AND 值变小,所以不可能加入相同的数。
于是我们可以得到一个 $O(n^2)$ 的 dp。
设 dp[i] 表示加入若干个数使得当前 AND 值为 i 的最小花费。
转移暴力枚举下一个填什么数。
注意到状态 i 能转移到的状态一定是 i 的子集。而枚举所有子集的复杂度是 $O(a_i^{\log_2 3})$ 的,所以我们可以考虑从这里找到本题的突破口。
我们现在要做的是判断 i 是否能转移到 j 。也就是是否存在一个 k ,使得 $i\ {\rm and}\ a_k = j$ 。
由于 i>j ,所以上式等价于:(~i) and (~a[k]) > 0, i xor ((~i) and (~a[k])) = j 。
于是我们考虑预处理出每一个值 v 是否满足 “存在一个 k ,使得 a[k] and v = v” 。于是 dp 转移的时候就枚举一下自己判定一下就可以了。
但是这样转移可能会导致一些本来没有的转移被转移了,但是显然这个不影响最优解。
时间复杂度:
$$O(a_i ^{\log_2 3})$$
代码
#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> vi;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=1<<18;
const LL INF=1e18;
int n,t=18;
int a[N],vis[N];
int And=(1<<t)-1;
LL dp[N];
int main(){
n=read();
For(i,1,n){
a[i]=read();
And&=a[i];
}
For(i,1,n)
a[i]^=And;
For(i,1,n)
vis[(N-1)^a[i]]=1;
For(i,0,t-1)
For(j,0,N-1)
if (~j>>i&1)
vis[j]|=vis[j|1<<i];
For(i,0,N-1)
dp[i]=INF;
For(i,1,n)
dp[a[i]]=a[i];
Fod(i,N-1,0){
if (dp[i]>=dp[0])
continue;
for (int j=i;j>0;j=(j-1)&i)
if (vis[j])
dp[i^j]=min(dp[i^j],dp[i]+(i^j));
}
cout<<(LL)And*n+dp[0]<<endl;
return 0;
}
UOJ#370. 【UR #17】滑稽树上滑稽果 动态规划的更多相关文章
- U68464 滑稽树上滑稽果(guo)
U68464 滑稽树上滑稽果(guo) 题目描述 小小迪有 n 个约会对象,每个对象有一个约会时长 p[i],小小迪 想尽可能多的去完成他的约会(假设小小迪可以瞬移),每个对象还有 一个忍耐时间 q[ ...
- uoj#370【UR #17】滑稽树上滑稽果
题目 低智选手果然刷不动uoj 首先考虑一下构造一棵树显然是骗你玩的,按位与这个东西越做越小,挂到链的最下面显然不会劣于挂到之前的某一个点下面,所以我们只需要求一个排列使得答案最小就好了 设\(A=\ ...
- UOJ#370. 【UR #17】滑稽树上滑稽果
$n \leq 1e5$个点,每个点有个权值$a_i \leq 2e5$.现将点连成树,每个点$i$的链接代价为$a_i \ \ and \ \ i父亲的代价$,这里的$and$是二进制按位与,求最小 ...
- 【做题】uoj#370滑稽树上滑稽果——巧妙dp
一个显然的结论是最终树的形态必然是一条链.具体证明只要考虑选定树上的某一条链,然后把其他部分全部接在它后面,这样答案一定不会变劣. 那么,一开始的想法是考虑每一位的最后出现位置,但这并不容易实现.注意 ...
- A. 【UR #17】滑稽树上滑稽果
题解: 首先很显然的是这是一条链(特殊数据说是链是故意让人迷茫的??) 然后 自己就开始yy 觉得每一次是加入一个使得当前值最小的数 然而这tm又是特殊数据?? 那就写一波发现是错的 考虑一下特殊数据 ...
- UOJ370 滑稽树上滑稽果 【状压DP】
题目分析: 答案肯定是链,否则可以把枝干放到主干. 去除一直存在的位,这样0位占满时就会结束. 用$f[S]$表示0位填埋情况,每次转移是它的一个子集,我们考虑可否转移. 再用$g[S]$存储转移是否 ...
- 吉首大学2019年程序设计竞赛(重现赛)I 滑稽树上滑稽果 (莫队+逆元打表)
链接:https://ac.nowcoder.com/acm/contest/992/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K ...
- 吉首大学校赛 I 滑稽树上滑稽果 (Lucas + 莫队)
链接:https://ac.nowcoder.com/acm/contest/925/I来源:牛客网 题目描述 n个不同的滑稽果中,每个滑稽果可取可不取,从所有方案数中选取一种,求选取的方案中滑稽果个 ...
- 【UOJ#33】【UR#2】树上GCD 有根树点分治 + 容斥原理 + 分块
#33. [UR #2]树上GCD 有一棵$n$个结点的有根树$T$.结点编号为$1…n$,其中根结点为$1$. 树上每条边的长度为$1$.我们用$d(x,y)$表示结点$x,y$在树上的距离,$LC ...
随机推荐
- pandas的读写
import as pd import numpy as np import matplotlib.pyplot as plt #df.to_excel('C:Users/history/Deskto ...
- linux系统中日常运维常用命令汇总一
一.查看日志和机器相关信息常用命令 1.cat cat 命令连接文件并打印到标准输出设备上,cat经常用来显示文件的内容,类似于下的type命令注意:当文件较大时,文本在屏幕上迅速闪过(滚屏),用户往 ...
- 【Mac上的PotPlayer视频播放器】Movist Pro for Mac 2.1.2
[简介] Movist 是Mac上最好用的视频播放器之一,功能齐全,类似Windows上的PotPlayer,今天和大家分享最新的 2.1.2 中文版本,Movist 支持几乎所有常见的视频格式,包括 ...
- Tomcat系列(9)——Tomcat 6方面调优(内存,线程,IO,压缩,缓存,集群)
核心部分 内存 线程 IO 压缩 缓存 集群 一.JVM内存优化 Tomcat内存优化,包括内存大小,垃圾回收策略. Windows 下的catalina.bat,Linux 下的catalina.s ...
- MySql分页查询慢|这里告诉你答案
一.背景 我们在开发的过程中使用分页是不可避免的,通常情况下我们的做法是使用limit加偏移量:select * from table where column=xxx order by xxx li ...
- Contest2163 - 2019-3-28 高一noip基础知识点 测试6 题解版
传送门 @dsfz201814 改题 T1:全锕,过 T2:全锕,过 T3:@dsfz201814 先用竖着放置的木块将它变成高度差最大为1的数列 然后对于任意相邻相等的两块,可以将它看成任意 例如, ...
- zip4j实现文件压缩与解压缩 & common-compress压缩与解压缩
有时候需要批量下载文件,所以需要在后台将多个文件压缩之后进行下载. zip4j可以进行目录压缩与文件压缩,同时可以加密压缩. common-compress只压缩文件,没有找到压缩目录的API. 1. ...
- JVM虚拟机和垃圾回收算法
类加载机制 双亲委派模型 垃圾回收算法 CMS G1 类加载机制 双亲委派模型 双亲委派模型: 需要加载一个类,先委托父类加载,父类找父类,依次递归加载;加载不到再由自己加载 垃圾回收算法 JVM的内 ...
- 肺结节CT影像特征提取(五)——肺结节CT影像ROI区域灰度直方图及其图形化
在博客肺结节CT影像特征提取中,已经实现了肺结节的灰度.纹理和形态特征的提取.但是,对于进一步了解ROI区域像素值或者说CT值的分布来说,还存在一定的不足,不能够很好的显示ROI区域. 因此,本文将进 ...
- python操作redis命令
Python操作redis from redis import StrictRedis, ConnectionPoolredis_url="redis://:xxxx@112.27.10.1 ...