对于一个整数序列 {a1,a2,…,an},我们定义它的变换为 {b1,b2,…,bn},其中 bi=a1∣a2∣…∣ai,其中 ∣ 表示二进制按位或运算。
现在求有多少个长为 n 的序列 a,满足 1≤ai≤2k−1,使得它的变换 b 是严格单调递增的,对 109+7 取模。
1≤n≤1018,1≤k≤3×104。
我们设 dpi,j,0/1 表示序列有 i 个数,当前或和第 j 位(二进制)是 0/1 的方案数
好难转移啊/ll
如果设 dpi,j 表示序列有 i 个数,当前或和为 j 的方案数呢?
那么我们可以枚举 j 的二进制中 1 的个数来转移!
所以说正确的状态应该是 dpi,j 表示序列有 i 个数,当前或和二进制有 j 个 1。
推一下柿子:
dpi,j=l=0∑j(lj)dpi−1,l2l
这个柿子的意思是,枚举前 i−1 项的或和有多少个 1 和这些 1 在哪里,然后第 i 项的剩下 j−l 个 1 的位置必须是 1,但是 l 个 1 的位置可以是 0 也可以是 1。
拆组合数:
dpi,j=j!l=0∑jl!dpi−1,l2l(j−l)!1
考虑换一种转移方式,有:
dpa+b,j=l=0∑j(lj)dpa,ldpb,j−l2bl
这个柿子的意思是,枚举前 a 项的或和有多少个 1 和这些 1 在哪里,然后剩下 b 项补足前 a 项没有的 1,并且这 b 项的被前 a 项占用的那些位置可以填 0/1。
然后拆一下组合数:
dpa+b,j=j!l=0∑jl!2bldpa,l(j−l)!dpb,j−l
也就是说,我们可以这样倍增转移:
⎩⎪⎪⎨⎪⎪⎧dpn,i=i!j=0∑ij!dpn−1,j2j(i−j)!1dp2n,i=i!j=0∑ij!2njdpn,j(i−j)!dpn,i−j
好了,用 MTT 优化就行。