题解:HDU 7438

Link

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]);
}
posted @ 2025-04-17 19:46  陈牧九  阅读(29)  评论(0)    收藏  举报