contain
我们可以发现,本质上其实就是选一个数,将其的 \(1\) 不断变为 \(0\) 是否能凑出 \(x\),那么我们可以考虑设 \(dp_i\) 表示 \(i\) 是否被 "包含",那么我们可以考虑转移 \(dp_i \rightarrow dp_{i \oplus {(1 << j)}}\) 前提是 \((bool)(i \& (1 << j)) == true\)
move
我们可以处理出每一个点有那些可以通过的时间,如图(绿色表示可通过,红色表示闸门)
那么我们可以将一个绿色的区间看作一个点,那么我们可以将绿色的区间之间互相连边,如图,我编个号:
第 \(1\) 列,编号为 \(1\),区间为 \([1, 1]\)
第 \(1\) 列,编号为 \(2\),区间为 \([51, 1e18]\)
第 \(2\) 列,编号为 \(3\),区间为 \([1, 1e18]\)
第 \(3\) 列,编号为 \(4\),区间为 \([1, 1]\)
第 \(3\) 列,编号为 \(5\),区间为 \([6, 1e18]\)
那么我们将区间之间建边,我们可以按照下图来建边(箭头表示边)
简单来说,假设有两个区间分别为 \([l, r]\),\([a, b]\) 那么如果 \(a >= l 且 a <= r\) 或 \(b >= l 且 b <= r\) 就可以建边,易得边的总数与区间的总数都是 \(n\) 的级别,我们可以用这些区间的编号跑一次 \(dij\),然后答案就是最后一列的区间中的答案的最小值