Link
先考虑计算(l=1,r=n)时的答案。
很显然我们可以dp,设(f_{i,j})表示考虑前(i)个数,NDS末尾为(j)的方案数,那么转移为:
[f_{i,j}=
egin{cases}
f_{i-1,j}&j
e a_i\
f_{i-1,j}+sumlimits_{l=1}^{a_i}f_{i-1,l}&j=a_i
end{cases}
]
考虑写成矩阵的形式,设(F_i=egin{pmatrix}f_{i,1}&cdots&f_{i,k}end{pmatrix},T_x),其中(T_{x,i,j}=[i=j]+[ile xwedge j=x])。
那么答案为:
[egin{pmatrix}1&0&cdots&0end{pmatrix}prodlimits_{i=1}^nT_{a_i}egin{pmatrix}1\vdots\1end{pmatrix}
]
然后我们考虑一般的情况,不难发现(T_{x,i,j}^{-1}=[i=j]-frac12[ile xwedge j=x])。
考虑预处理:
[egin{aligned}
p_i&=prodlimits_{j=1}^iT_{a_j}egin{pmatrix}1\vdots\1end{pmatrix}\
q_i&=egin{pmatrix}1&0&cdots&0end{pmatrix}prodlimits_{j=i}^1T_{a_i}^{-1}
end{aligned}
]
那么询问((l,r))的答案就是(q_{l-1}p_r)。
注意右乘(T_x)和左乘(T_x^{-1})均可以(O(n^2))完成,因此时间复杂度为(O(nk^2+qk))。
#include <cstdio>
const int N=50007,K=27,P=1000000007;
int a[N],mat[K][K],f[N][K],g[N][K];
int read(){int x;scanf("%d",&x);return x;}
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
int div(int x){return x&1? (x+P)/2:x/2;}
int main()
{
int n=read(),k=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=k;++i) for(int j=1;j<=k;++j) mat[i][j]=i==j;
for(int t=1;t<=n;++t)
{
for (int i=1;i<=a[t];++i) for(int j=a[t];j>=i;--j) inc(mat[i][a[t]],mat[i][j]);
for(int i=1;i<=k;++i) for(int j=i;j<=k;++j) inc(f[t][i],mat[i][j]);
}
for(int i=1;i<=k;++i) for(int j=i;j<=k;++j) mat[i][j]=i==j;
for(int t=1;t<=n;++t)
{
for(int i=1;i<=k;++i) g[t][i]=mat[1][i];
for(int i=1;i<=a[t];++i) for(int j=a[t];j<=k;++j) inc(mat[i][j],P-div(mat[a[t]][j]));
}
for(int q=read(),l,r,ans;q;--q)
{
l=read(),r=read(),ans=0;
for(int i=1;i<=k;++i) inc(ans,1ll*g[l][i]*f[r][i]%P);
printf("%d
",ans);
}
}