P5488 差分与前缀和 题解


题面

推式子+二项式定理+FFT。这个题需要一点生成函数的知识。

首先考虑前缀和,求一个多项式 \(F(x)\) 的前缀和相当于是卷上了一个系数全是 \(1\) 的多项式。即

\[\begin{aligned} Sum(x)&=F(x)\times \sum_{i=0}^{\infty}x^i\\ &=F(x)\times \frac{1}{1-x} \end{aligned} \]

那么 \(k\) 阶前缀和即

\[\begin{aligned} Sum(x)&=F(x)\times \frac1{(1-x)^k}\\ &=F(x)\times (1-x)^{-k}\\ &=F(x)\times \sum_{i=0}^{\infty}\binom{k+i-1}{i-1}x^i \end{aligned} \]

使用FFT/NTT优化即可。

考虑到差分是前缀和的逆运算,则

\[\begin{aligned} Dif(x)&=F(x)\times (1-x)^k\\ &=F(x)\times \sum_{i=0}^{\infty}(-1)^i\binom{k-i+1}{i}x^i \end{aligned} \]

同样的道理,直接FTT/NTT即可。

点击查看代码
#include
#include
using namespace std;
const int N=4e5+13,P=1004535809,G=3;
inline int qpow(int a,int k){int s=1;for(;k;k>>=1,a=1ll*a*a%P)if(k&1)s=1ll*s*a%P;return s;}
inline int Inv(int a){return qpow(a,P-2);}
const int Gi=Inv(G);
inline int rd(){
	long long res=0;char c=getchar();
	for(;!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())res=((res<<1)+(res<<3)+(c-'0'))%P;
	return res;
}
int n,k,op,r[N],a[N],b[N];
inline void fft(int *f,int type,int limit){
	for(int i=0;i>1]>>1)|((i&1)<<(l-1));
	fft(a,1,limit),fft(b,1,limit);
	for(int i=0;i