很没用的总结,如果您发现了错误,欢迎指正!!
一维一阶前缀和
对于一个数组 (A),设其前缀和数组为 (sum)
(sum_i) 的意义是 (sumlimits_{k=1}^iA_k),即区间 ([1,i]) 所有数的和
显然对于不带修改的区间求和,我们可以用前缀和数组 (O(1)) 查询
即 (sumlimits_{i=l}^rA_i=sum_{r}-sum_{l-1})
构造
构造前缀和数组:(sum_i=sum_{i-1}+A_i)
一维一阶差分
对于一个数组 (A),设其差分数组为 (dif)
(dif_i) 的意义是 (A_i-A_{i-1}),即相邻两个数的差
对于单点或区间加减法,如果最后只是求修改完毕后的数列,那么我们可以 (O(1)) 修改,最后 (O(n)) 还原
即 ([l,r]+addRightarrow dif_l+add,dif_{r+1}-add)
最后 (A_i=sumlimits_{k=1}^idif_k)
构造
构造差分数组:(dif_i=A_i-A_{i-1})
高维一阶前缀和
对于一个高维数组 (A),设其前缀和数组为 (sum)
(sum_{i_1,cdots,i_k}) 的意义是区间 ((1,cdots,1)sim(i_1,cdots,i_k)) 内所有数的和
利用容斥原理,即可对不带修改的高维区间求和询问 (O(1)) 回答
构造
(k) 维前缀和即利用 (k) 重循环直接加法计算
(sum_{i_1,cdots,i_k}=sum_{i_1,cdots,i_{k-1}}+A_{i_1,cdots,i_k})
高维一阶差分
对于一个高维数组 (A),设其差分数组为 (dif)
对于一个 (k) 维区间加法,我们要对其区间开端 (+1),区间末端 (-1)
例如 (2) 维区间加法 ((x,y)sim(u,w))
显然 (dif_{x,y}+1,dif_{u+1,y}-1,dif_{x,w+1}-1,dif_{u+1,w+1}+1)
推广到一般即为高维的情况
构造
略
一维高阶前缀和
高阶前缀和具有组合意义
对于一个数组 (A),设其 (k) 阶前缀和数组为 (sum_k)
其一阶前缀和 (sum_{1,i}=sum_{1,i-1}+A_i)
对数组 (sum_{k-1}) 再做前缀和,得到的前缀和数组即为其 (k) 阶前缀和数组 (sum_k)
构造
构造一维高阶前缀和数组:
一维高阶差分
高阶差分具有组合意义
对于一个数组 (A),设其 (k) 阶差分数组为 (dif_k)
其一阶差分 (dif_i=A_i-A_{i-1})
对数组 (dif_{k-1}) 再做差分,得到的差分数组即为其 (k) 阶差分数组 (dif_k)
构造
生成函数优化
本处讨论一维高阶的情况
设序列 (a) 的普通生成函数 (f(x)) 为 (sumlimits^{infty}_{n=0}a_nx^n),(g(x)=sumlimits^infty_{n=0}b_nx^n) 是另一个新的数列 ({b_n}^infty_{n=0}) 的生成函数
高阶前缀和
首先写出前缀和的计算方法:(sum_i=sumlimits_{k=1}^ia_k)
熟知 (f(x)g(x)) 是数列 (left{sumlimits^n_{k=0}a_kb_{n-k} ight}_{n=0}^infty) 的生成函数 (性质1)
当 (b) 的每一项 (b_i) 都等于 (1) 时,(dfrac{f(x)}{1-x}) 即为其一阶前缀和
同理,二阶前缀和是在一阶前缀和的基础上得到的,(k) 阶前缀和是在 (k-1) 阶前缀和的基础上得到的,我们用 (dfrac{1}{1-x}) 不断相乘即可
所以 (k) 阶前缀和即为 (f imesdfrac{1}{(1-x)^k})
根据上文性质1,(dfrac{1}{(1-x)^k}) 即为 (left{sumlimits_{n_1+n_2+dots+n_k=n}1 ight}_{n=0}^infty) 的OGF
考虑组合意义,即 (left{dbinom{n+k-1}{n} ight}_{n=0}^infty) 的OGF
递推组合数:
(dbinom{i+k-1}{i}=dbinom{i+k-2}{i-1}dfrac{k+i-1}{i})
然后跟 (f) NTT卷一下就可以
高阶差分
首先写出差分的计算方法:(dif_i=a_i-a_{i-1})
依然考虑性质1,如果 (b_0=1,b_1=-1,b_i=0;(i>1))
此时 (f imes g=sumlimits_{n=0}^inftyleft(sumlimits^n_{k=0}a_kb_{n-k} ight)x^n=sumlimits_{n=0}^infty(a_n-a_{n-1})x^n)
显然我们依然能将差分数组的计算方法写成生成函数相乘的形式
此时数列 (b) 即为 (1-x)
所以 (k) 阶差分即为 (f imes(1-x)^k)
对于 ((1-x)^k) 直接二项式定理拆开
((1-x)^k) 的每项系数是 (sumlimits_{i=0}^k(-1)^idbinom{k}{i})
递推组合数:
(dbinom{k}{i}=dbinom{k}{i-1}dfrac{k-i+1}{i})
然后拿 (f) NTT卷一下就可以
是不是非常非常简单?
放放代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 1000001
#define INF 1100000000
#define Kafuu return
#define Chino 0
#define fx(l,n) inline l n
#define set(l,n,ty,len) memset(l,n,sizeof(ty)*len)
#define cpy(f,t,ty,len) memcpy(t,f,sizeof(ty)*len)
#define R register int
#define int long long
using namespace std;
const int mod=1004535809,pr=3;
int n,k,t,ori[N],invp,invx,x=1,br[N],prp[N],binom[N],T[N];
fx(int,gi)(){
char C=getchar();long long n=0,f=1;
while(C<'0'||C>'9'){
if(C=='-') f=-f;
C=getchar();
}
while(C>='0'&&C<='9') ((n*=10)+=C-'0')%=mod,C=getchar();
return (n*f)%mod;
}
fx(int,pow)(int a,int b=mod-2){
int sum=1;
while(b){
if(b&1) (sum*=a)%=mod;
(a*=a)%=mod;
b>>=1;
}
return sum;
}
fx(void,NTT)(int *f,short r){
R len,hl,exp,uni,st,i;
for(i=0;i<x;i++) if(i<br[i]) swap(f[i],f[br[i]]);
for(len=2,hl=1;len<=x;hl=len,len<<=1){
exp=pow(r==1?pr:invp,(mod-1)/len);
for(i=1;i<hl;i++) prp[i]=prp[i-1]*exp%mod;
for(st=0;st<x;st+=len){
for(i=0;i<hl;i++){
uni=prp[i]*f[i|st|hl]%mod;
f[i|st|hl]=(f[i|st]-uni+mod)%mod;
f[i|st]=(f[i|st]+uni)%mod;
}
}
}
}
signed main(){
n=gi(),k=gi(),t=gi();
for(R i=0;i<n;i++) T[i]=ori[i]=gi();
while(x<=n+n) x<<=1;
for(R i=0;i<x;i++) br[i]=(br[i>>1]>>1)|((i&1)?x>>1:0);
invx=pow(x);invp=pow(pr);binom[0]=1;
if(!t) for(int i=1;i<=n;i++) binom[i]=binom[i-1]*(k+i-1)%mod*pow(i)%mod;
else for(int i=1;i<=n;i++) binom[i]=-binom[i-1]*(k-i+1)%mod*pow(i)%mod;
prp[0]=1;NTT(ori,1);NTT(binom,1);
for(int i=0;i<x;i++) (ori[i]*=binom[i])%=mod;
NTT(ori,-1);
for(int i=0;i<n;i++) cout<<ori[i]*invx%mod<<" ";
}
树上前缀和
树上前缀和即是快速回答两点间距离的一种手段,(sum) 数组表示当前点到根结点的距离
于是两点间距离即为 (sum_x+sum_y-sum_{lca})
构造
(sum_{x}=sum_{fa}+v_{fa o x})
树上差分
对点差分
即为路径上的点同加一个值 (val)
对于每个点(p),设 (S) 为其子结点集合,(dif_p=sumlimits_{tin S}dif_t)
注意自下向上有序统计,不要随便找一个点套用上边的式子
构造
(dif_x+1,dif_y+1,dif_{lca}-1,dif_{lcafa}-1)
对边差分
即为路径上的边同加一个值 (val)
(dif_p) 表示边 (fa o p)
统计同对点差分
构造
(dif_x+1,dif_y+1,dif_{lca}-2)
你已经看完啦,相信你已经理解并精通了前缀和与差分,快去研究高维高阶前缀和&高维高阶差分吧!