题解 P4310 【绝世好题】
先无良宣传一下博客
文章列表 - 核融合炉心 - 洛谷博客
知识点:DP , 奇妙思路 , 暴力枚举(?)
一道绝世好题
-
题目要求:
求
a 的子序列b 的最长长度,
满足bi\ \&\ bi-1\not=0 n \le 1e5 , a_i \le 1e9 -
暴力思路:
类比最长上升子序列
直接
O(n^2) 暴力枚举
当前要添加的数,以及序列b 结尾的数设
f[i] 表示以a[i] 结尾的b 序列的最长长度
则: 状态转移方程式为:\large f[i] = max(f[i], f[j]+1)\ (a[i]\ \&\ a[j] \not=0) 可以取得
90 分的好成绩(大雾) -
考虑优化
发现新添加的数,
只能由:
在同一二进制位上 , 同为1的数转移而来也就是说,
可以选择 枚举
新添加的数的 二进制上的1位考虑枚举二进制位
并记录 :
此二进制位全为为1 的数 组成的 子序列b
所能达到的最大长度为多少设
f[i] 表示 : 最后一位为i 的b 数列的最长长度,$k$ 为 枚举的: $a[i]$ 中 , 二进制上为 $1$ 的二进制位数 则可以推出新的状态转移方程式: $ \large f[i] = max(f[i] , bit[k]+1) 这样 就可以少一层循环
来枚举 新添加的数 可接到 哪些数之后.更新完
f[i] 后 , 再用更新后的f[i] ,
反过来 更新bit[k] 对于枚举
k , 可以使用lowbit() , 并取其log 函数值来获得
在更新f[i] 的过程中取最大的f[i] 作为答案
最后优化到了O(31 \times n) .
(因为最多只有31 个二进制位上的1 )
上代码:
修复了暴力思路的
并添加了代码