遇到一道题求f(x)=sigma f(i)×f(x-i)这样的,做法是这样的:(下面F与G都与f有关),不严谨的一个证明:考虑左端点为1,例如[1...8]区间,那么求完[1...4],此时考察的是两项都是左区间相乘对右边点的贡献,比如5,能发现f[1] * f[4] 以及f[4] * f[1]都有了,因此只要像正常分治fft做即可;左端点不是1时,比如[5..8] 中[5,6]对[7,8]贡献,可以发现此时考察的是一项为左区间另一项为之前已经算出来的值相乘对右端点贡献(因为容易证明递归到的区间[l..r]当l>1时一定有l*2 > r),那么此时像正常分治做就只计算了一次f[7]+=f[2] * f[5],需要额外计算一个f[7] += f[5] * f[2]
if(l==r)
{
if(l==1)f[l]=1;
else Mul(f[l],jc[l-2]);
return;
}
int mid=(l+r)>>1;
sol(l,mid);
pre_ntt(r-l+2);
for(int i=0;i<len;i++)A[i]=B[i]=0;
for(int i=l;i<=mid;i++)A[i-l]=F(i);//1LL*(jc[i-1]-f[i]+mod)%mod*ijc[i-1]%mod;
for(int i=1;i<=r-l;i++)B[i]=G(i);
ntt(A,0),ntt(B,0);
for(int i=0;i<len;i++)A[i]=1LL*A[i]*B[i]%mod;
ntt(A,1);
for(int i=mid+1;i<=r;i++)Ad(f[i],A[i-l]);
if(l>1)
{
for(int i=0;i<len;i++)A[i]=B[i]=0;
for(int i=l;i<=mid;i++)A[i-l]=G(i);//1LL*(jc[i-1]-f[i]+mod)%mod*ijc[i-1]%mod;
for(int i=1;i<=r-l;i++)B[i]=F(i);
ntt(A,0),ntt(B,0);
for(int i=0;i<len;i++)A[i]=1LL*A[i]*B[i]%mod;
ntt(A,1);
for(int i=mid+1;i<=r;i++)Ad(f[i],A[i-l]);
}
sol(mid+1,r);