高维前缀和

引入

给定\(num\)个三元组\((x,y,z)\)。每次询问满足\(x \leq qx\) ,\(y \leq qy\) ,\(z \leq qz\) 的三元组个数。

\(x,y,z \leq n\)\(n \leq 10\)\(q ,num\leq 10^6\)

求解

容易想到维护\(Pre(x,y,z)\) 表示\(x' \leq x\) , \(y' \leq y\) , \(z' \leq z\) 的三元组个数

思路1

利用容斥原理求解。

由于容斥涉及的情况数目达到\(2^m\),故求解\(m\)维前缀和时间复杂度\(O(2^mn^m)\)\(m\)较大时难以求解。

\[Pre(x,y,z)=A(x,y,z)+Pre(x-1,y,z)+Pre(x,y-1,z)+Pre(x,y,z-1)-Pre(x-1,y-1,z)-Pre(x-1,y,z-1)-Pre(x,y-1,z-1)+Pre(x-1,y-1,z-1) \]

思路2

考虑1维1维地累加(而不是思路1中的多维共同累加再减去重复的)

具体地,初始令\(Pre(x,y,z)=A(x,y,z)\),运算分多步执行:

  1. \(Pre(x,y,z)=\sum_{z'=1}^zPre(x,y,z')\)
  2. \(Pre(x,y,z)=\sum_{y'=1}^{y}Pre(x,y',z)\)
  3. \(Pre(x,y,z)=\sum_{x'=1}^{x}Pre(x',y,z)\)

求解m维前缀和的时间复杂度为\(O(mn^m)\)

实际执行时,将m元组压成m位n进制数作为数组下标 求解

应用

Codeforces 449D

题意

给定n个m位数,问从中取出1些数,使得&值为0的方案数。答案对\(10^9+7\)取模,\(n \leq 10^6,m\leq 20\)

题解

本质上1个数等价于1个集合。则原问题等价于取出若干个集合,使其交集为空的方案数。

总体思路自然是容斥原理

抽象成函数,记\(f(s)\)表示交集包含\(s\)的方案数,\(cnt(s)\)表示\(s\)中1的个数则

\[Ans=\sum_{s=0}^{2^m}f(s)(-1)^{cnt(s)} \]

首先考虑\(f(s)\)的求解

由于\(s\)交集,故本质上只需求出包含集合\(s\)的集合个数\(num(s),则\)\(f(s)=2^{num(s)}-1\)

\(num(s)\)为给出的\(n\)个集合中\(s\)的超集个数,等价于求解“高维后缀和”。

而高维后缀和的实现可以转化为高维前缀和的逆序循环+反向贡献

由此可在\(m2^m\)时间内求出所有\(f(s)\),然后在\(2^m\)时间内求解\(Ans\)

时间复杂度\(O(m2^m)\) 代码见此

posted @ 2019-05-07 17:03  littlewyy  阅读(473)  评论(0编辑  收藏  举报