对于给定序列 ({a_n},ngeq 1) ,需要快速求解其 (k) 阶差分或 (k) 阶前缀和。
生成函数可对 (O(kn)) 的朴素算法进行优化。
先考虑差分:
我们不妨拓宽定义 (a_0=0,a_m=0(m>n))
定义 ({a_n}) 的 OGF 为 (displaystyle A(x)=sum_{n=0}^infty a_nx^n)
设其差分序列 ({d_n}) 满足 (d_0=0,d_n=a_n-a_{n-1}(n>0)) , OGF 为 (displaystyle D_1(x)=sum_{n=0}^infty d_nx^n)
可以比较显然的发现 (displaystyle D_1(x)=sum_{n=0}^infty d_nx^n=sum_{n=1}^infty (a_n-a_{n-1})x^n=A(x)-xA(x)=(1-x)cdot A(x))
因此可以进一步得到 (D_k(x)=(1-x)cdot D_{k-1}(x)=cdots =(1-x)^kcdot A(x))
只要展开即可得到高阶差分的值
考虑前缀和:
法一:
设该序列前缀和序列 ({s_n}) 满足 (displaystyle s_n=sum_{i=1}^n a_i(ngeq 0)) , OGF 为 (displaystyle S_1(x)=sum_{n=0}^infty s_nx^n)
代入 (s_n) 的定义式为 (displaystyle S_1(x)=sum_{n=0}^infty (sum_{i=0}^na_i)x^n)
令 (e_n=1(ngeq 0)) ,且 OGF 为 (displaystyle E(x)=sum_{n=0}^infty e_nx^n=sum_{n=0}^infty x^n={1over 1-x})
原式变换为 (displaystyle S_1(x)=sum_{n=0}^infty (sum_{i=0}^na_ie_{n-i})x^n=sum_{n=0}^infty (sum_{i+j=0}^na_ie_j)x^n)
系数显然满足卷积的性质,故得到 (displaystyle S_1(x)=(sum_{n=0}^infty a_nx^n)cdot (sum_{n=0}^infty e_nx^n)={1over 1-x}cdot A(x))
法二:
显然 (A(x)) 为 (S_1(x)) 差分形成,故 ((1-x)cdot S_1(x)=A(x)) 从而得到 (S_1(x)={1over 1-x}A(x))
进而可得 (S_k(x)={1over 1-x}S_{k-1}(x)=cdots ={1over (1-x)^k}cdot A(x))
只要展开即可得到高阶前缀和的值
由于高阶差分与高阶前缀和性质相似,故下文不再分开讨论,并统一以 (A_k(x)=(1-x)^kcdot A(x)) 表示
当 (k<0) 时,(A_k(x)={1over (1-x)^{|k|}}cdot A(x)) ,为 (k) 阶前缀和
当 (k>0) 时,(A_k(x)=(1-x)^{|k|}cdot A(x)) ,为 (k) 阶差分
当 (k=0) 时,(A_k(x)=A(x))
当类似原题,需求解前 (n) 项时,相当于给定 (A(x)) 与 (k) ,求解 (A_k(x)equiv (1-x)^kcdot A(x)pmod {x^n})
设 (B(x)equiv (1-x)^kpmod {x^n}) ,则 (A_k(x)equiv B(x)cdot A(x)pmod {x^n}) 可以用 FFT 或者 NTT 求解,复杂度为 (O(nlog n))
法一:
由于 (B(x)equiv (1-x)^kpmod {x^n}) ,且对 (forall kin Z,(1-x)^kequiv 1pmod x)
故直接两边取对数 (displaystyle ln B(x)equiv kcdot ln(1-x)pmod x^nequiv -kcdot int(sum_{i=0}^infty x^i) ext dxpmod {x^n})
因此 (displaystyle B(x)equiv exp[-kcdot int(sum_{i=0}^infty x^i) ext dx]pmod {x^n})
使用多项式积分、多项式指数函数即可求解,复杂度为 (O(nlog n))
法二:
考虑将 ((1-x)^k) 用广义牛顿二项式定理展开:(displaystyle (1-x)^k=sum_{n=0}^infty left( egin{matrix} k \ n end{matrix} ight)cdot (-1)^nx^n)
求解出前 (n) 项即可
又由于 (B[n]=left( egin{matrix} k \ n end{matrix} ight)cdot (-1)^n=(-1)^ncdot {k!over n!(k-n)!})
故 (B[n+1]=(-1)^{n+1}cdot {k!over (n+1)!(k-n-1)!}={n-kover n+1}B[n],B[0]=1)
因此, (O(n)) 预处理 (1)~(n) 逆元,而后 (O(n)) 递推即可求解 (B(x))
不难发现,生成函数优化过的,对于高阶差分与高阶前缀和的求解,复杂度为 (O(nlog n)) ,与阶数 (k) 无必然关系
故当阶数 (k>>log n) 时,显然优化过后的解法更优
- 若对于某常数 (C) ,使得 (a_n=C) 恒成立,求 (k) 阶差分((k<0) 时代表前缀和)
其本身可视为 (a_0=C,a_n=0(n>0)) 的一阶前缀和
故求解该序列 (k) 阶差分,等效于求解差分序列 ((k-1)) 阶差分
又因为 (D_1(x)=C,A_k(x)=(1-x)^{k+1}D_1(x)=Ccdot B(x)) ,可 (O(n)) 递推求出 (A_k[n]=Ccdot B[n])
- 若对于某常数 (C) ,使得 (a_n=C,ngeq m) 恒成立,求 (k) 阶差分
其本身可视为 (A(x)=x^mcdot {A(x)over x^m}) ,其中 ({A(x)over x^m}[n]=C,ngeq 0)
推法同上,也为 (O(n))
- 若对于某序列 ({a_n}) ,支持两种操作:
(1). 将某个指定的 (a_i) 增加常数 (c)
(2). 将整个序列求前缀和或差分
保证操作 (1) 全在操作 (2) 前,求最后的序列
不妨设所有操作 (1) 结束后,序列 ({a_n}) 变为序列 ({a_n+b_n})
之后求解前缀和或差分,则可记录 ((1-x)^k) 指数,最后直接相乘求解。不妨设操作 (2) 结束后,指数为 (k) 。
则 (Ans(x)=(1-x)^k[A(x)+B(x)]=A_k(x)+B_k(x))
可以见得, (1) 操作实际上对答案的影响为线性的,可以单独处理
- 若对于某序列 ({a_n}) ,支持两种操作:
(1). 将某个指定的 (a_i) 增加常数 (c)
(2). 将整个序列求前缀和或差分
求最后的序列
可以先求解出 (A_k(x)) ,之后单独考虑每次增加操作,设第 (i) 次操作位置为 (p_i) ,增加的值为 (c_i) ,之后的指数为 (k_i)
则由上面的线性可知,对答案的贡献为 (B_i(x)=c_icdot x^{p_i}cdot (1-x)^{k_i})
- 若对于某序列 ({a_n}) ,支持两种操作:
(1). 将某个指定的区间 ([l,r]) 所有 (a_i) 增加常数 (c)
(2). 将整个序列求前缀和或差分
求最后的序列
不妨在所有操作前先将整个序列进行一次前缀和,之后的 (1) 操作等效于将位置 (p_{l_i}) 的值增加 (c_i) ,并将位置 (p_{r_i+1}) 的值增加 ((-c_i))
考虑最后进行一次差分还原,其余操作同上
- 若对于某初始时恒为 (0) 的序列 ({a_n}) ,支持三种操作:
(1). 将某个指定的区间 ([l,r]) 所有 (a_i) 增加常数 (c)
(2). 将整个序列求前缀和或差分
(3). 查询当前子区间 ([l,r]) 的和
保证操作 (3) 数量较少
考虑离线 (3) 操作,对于每次该操作,考虑所有其前面的修改对该区间值的影响。
而若某次修改 (i) ,使得位置 (p_i) 增加 (c_i) ,之后进行了 (k_i) 阶差分
则对该询问的贡献为 (c_icdot x^{p_i}cdot (1-x)^{k_i}) 的 ([l,r]) 项
由于该部分项相加为 (displaystyle c_icdot sum_{j=l}^r(-1)^{j-p_i} left( egin{matrix} k_i \ j-p_i end{matrix} ight) =c_icdot sum_{j=l-p_i}^{r-p_i}(-1)^j left( egin{matrix} k_i \ j end{matrix} ight))
考虑 (k_i<0) 时,具有性质 ((-1)^j left( egin{matrix} k_i \ j end{matrix} ight)= left( egin{matrix} k_i+j-1 \ k_i-1 end{matrix} ight))
此时 (displaystyle c_icdot sum_{j=l-p_i}^{r-p_i}(-1)^j left( egin{matrix} k_i \ j end{matrix} ight)= c_icdot left( egin{matrix} k_i+l-p_i-1 \ k_i end{matrix} ight)+ c_icdot sum_{j=l-p_i}^{r-p_i} left( egin{matrix} k_i+j-1 \ k_i-1 end{matrix} ight)- c_icdot left( egin{matrix} k_i+l-p_i-1 \ k_i end{matrix} ight))
(left( egin{matrix} n \ m-1 end{matrix} ight)+ left( egin{matrix} n \ m end{matrix} ight)= left( egin{matrix} n+1 \ m end{matrix} ight))
(displaystyle left( egin{matrix} n \ m end{matrix} ight)+sum_{i=0}^t left( egin{matrix} n+i \ m-1 end{matrix} ight)= left( egin{matrix} n+1 \ m end{matrix} ight)+sum_{i=0}^{t-1} left( egin{matrix} n+1+i \ m-1 end{matrix} ight)= cdots= left( egin{matrix} n+t \ m end{matrix} ight))
故 (displaystyle c_icdot sum_{j=l-p_i}^{r-p_i}(-1)^j left( egin{matrix} k_i \ j end{matrix} ight)= c_icdot left( egin{matrix} k_i+r-p_i \ k_i end{matrix} ight)- c_icdot left( egin{matrix} k_i+l-p_i-1 \ k_i end{matrix} ight))