HDU-5730(CDQ+FFT/NTT)
题意:将长度为\(n\)的序列分成若干段,每段\([l,r]\)的权值为\(a_{r-l+1}\),一种分法的权值为所有段的乘积,求所有可能的分法的权值和
根据题意可以得到简单\(dp\)
\(dp_0=1,dp_i=\sum_0^{i-1}dp_j \cdot a_{i-j}\)
可以看到是一个\(i-j\)形式的作差卷积
但是直接卷积我们无法保证先求出了\(dp_j\),所有可以用\(CDQ\)分治优化,复杂度\(n\log^2 n\)
具体实现见代码
#include
using namespace std;
#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
template inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template inline void cmax(T &a,T b){ ((ai) swap(a[i],a[rev[i]]);
for(reg int i=1;i>1;
Solve(l,mid); //先求出左边所有的
int R=1,c=-1;
while(R<=r-l+1) R<<=1,c++;
rep(i,1,R) rev[i]=(rev[i>>1]>>1)|((i&1)<