zoukankan      html  css  js  c++  java
  • 论生成函数对序列高阶差分与高阶前缀和求解的优化

    对于给定序列 ({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) 时,显然优化过后的解法更优


    1. 若对于某常数 (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])


    1. 若对于某常数 (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))


    1. 若对于某序列 ({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) 操作实际上对答案的影响为线性的,可以单独处理


    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})


    1. 若对于某序列 ({a_n}) ,支持两种操作:
      (1). 将某个指定的区间 ([l,r]) 所有 (a_i) 增加常数 (c)
      (2). 将整个序列求前缀和或差分
      求最后的序列

    不妨在所有操作前先将整个序列进行一次前缀和,之后的 (1) 操作等效于将位置 (p_{l_i}) 的值增加 (c_i) ,并将位置 (p_{r_i+1}) 的值增加 ((-c_i))

    考虑最后进行一次差分还原,其余操作同上


    1. 若对于某初始时恒为 (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))

  • 相关阅读:
    Thread的run方法和start方法
    35. Search Insert Position
    Error:(1, 1) java: 非法字符: 'ufeff'
    final修饰的变量是引用不可变,还是对象不可变
    数组与练习
    java反射机制【转】
    Socket
    面向对象的设计原则和设计模式
    多线程
    为什么有时候修改了css文件,页面的样式却没有改变?
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/13693255.html
Copyright © 2011-2022 走看看