题解:HDU 7438
1. Description
给定一个长度为 \(n\) 的序列,询问序列中每种子序列出现次数的立方和。
2. Solution
一个不太常见的 \(trick\),出现次数的立方和等于选择三个相同的子序列方案数,那么就是类似一个 LCS 求方案数的做法,令 \(f_{i,j,k}\) 表示三个子序列分别以 \(a_i,a_j,a_k\) 结尾的方案数,加入前缀和优化即可。
那么转移方程显然 \(f_{i,j,k}=\begin{cases}f_{i-1,j,k}+f_{i,j-1,k}+f_{i,j,k-1}-f_{i-1,j-1,k}-f_{i-1,j,k-1}-f_{i,j-1,k-1}+f_{i-1,j-1,k-1}+1\ (a_i=a_j 且 a_j=a_k)\\f_{i-1,j,k}+f_{i,j-1,k}+f_{i,j,k-1}-f_{i-1,j-1,k}-f_{i-1,j,k-1}-f_{i,j-1,k-1}+f_{i-1,j-1,k-1}\ others\end{cases}\)。
3. Code
/*by qwer6*/
/*略去缺省源和快读快写*/
const int N=255,mod=998244353;
int n;
int a[N],f[N][N][N],g[N][N][N];
int add(int x,int y){
x+=y;
return x>=mod?x-mod:x;
}
int sub(int x,int y){
x-=y;
return x<0?x+mod:x;
}
int add(int x,int y,int z){
return add(add(x,y),z);
}
signed main(){
read(n);
for(int i=1;i<=n;i++)read(a[i]);
for(int i=1,sum1,sum2;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
f[i][j][k]=sub(add(add(f[i-1][j][k],f[i][j-1][k],f[i][j][k-1]),f[i-1][j-1][k-1]),add(f[i-1][j-1][k],f[i-1][j][k-1],f[i][j-1][k-1]));
if(a[i]==a[j]&&a[j]==a[k])f[i][j][k]=add(f[i][j][k],f[i-1][j-1][k-1],1);
}
}
}
write(f[n][n][n]);
}

浙公网安备 33010602011771号