AT_abc237_f [ABC237F] |LIS| = 3 题解

分析

通过题目我们可以发现,题目里唯一难受的限制就是最长增长部分的长度。我们不妨试试将其放进状态函数里。根据 LIS 的性质,若一个长度为 3 的子序列 a1,a2,a3 满足 LIS,则必有 a1<a2<a3。我们定义 fi,x,y,z 表示在前 i 个数中,长度为 1 的 LIS 的最小 a1 值为 x,长度为 2 的 LIS 的最小 a2 值为 y,长度为 3 的 LIS 的最小 a3 值为 z(这里的 a1,a2,a3 相互独立)。

考虑从 i 扩散到 i+1,有转移方程:

fi+1,x,y,z={fi+1,x,y,z+fi,x,y,z1xxfi+1,x,y,z+fi,x,y,z1yyfi+1,x,y,z+fi,x,y,z1zz

这里的 x,y,z 也是独立的,如果不理解,可以看看具体的代码。

我们根据性质 x<y<z,可以得到初始化:f0,m+1,m+2,m+3=1。因为在 i=0 的时候,是可取 1m 的所有。

最后的答案,就是所有的满足 x<y<zfn,x,y,z 的和。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
const int N=1005,M=15;
const int p=998244353;
int f[N][M][M][M];
void solve(){
	cin>>n>>m;
	f[0][m+1][m+2][m+3]=1;
	for(int i=0;i<n;i++)
		for(int now_x=1;now_x<=m+3;now_x++)
			for(int now_y=now_x+1;now_y<=m+3;now_y++)
				for(int now_z=now_y+1;now_z<=m+3;now_z++)
					for(int now=1;now<=m;now++){
						if(1<=now&&now<=now_x) f[i+1][now][now_y][now_z]=(f[i+1][now][now_y][now_z]+f[i][now_x][now_y][now_z])%p;
						else if(now_x<now&&now<=now_y) f[i+1][now_x][now][now_z]=(f[i+1][now_x][now][now_z]+f[i][now_x][now_y][now_z])%p;
						else if(now_y<now&&now<=now_z) f[i+1][now_x][now_y][now]=(f[i+1][now_x][now_y][now]+f[i][now_x][now_y][now_z])%p;
	int ans=0;
	for(int x=1;x<=m;x++)
		for(int y=x+1;y<=m;y++)
			for(int z=y+1;z<=m;z++)
				ans=(ans+f[n][x][y][z])%p;
	cout<<ans;return ;
}
signed main(){
	solve();return 0;
}
posted @   harmis_yz  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示