[题解]ABC358E Alphabet Tiles

AtCoder ~ E - Alphabet Tiles
Luogu ~ ABC358E Alphabet Tiles

题意简述

给定正整数 \(K\)\(C_1,C_2,\dots,C_{26}\)。请求出长度在 \(1\)\(K\) 之间,满足下列条件的字符串个数(取模 \(998244353\)):

  • 该字符串全由大写字母组成。
  • 对于 \(1\le i\le 26\),下面条件成立:
    • \(a_i\) 为第 \(i\) 个大写字母,比如 \(a_5=\) E
    • 该字符串中,\(a_i\) 出现的次数不超过 \(C_i\)

解题思路

我们考虑dp。设 \(f[i][j]\) 为用前 \(i\) 种字母,组成长度为 \(j\) 的字符串个数。

归纳得出,“前 \(i\) 种字母,组成长度为 \(j\)”,就相当于下面几种情况求和:

  • \(i-1\) 种字母,组成长度为 \(j\)
  • \(i-1\) 种字母,组成长度为 \(j-1\),再在中间插入 \(1\) 个字母 \(i\)
  • \(\dots\)
  • \(i-1\) 种字母,组成长度为 \(j-t\),再在中间插入 \(t\) 个字母 \(i\)

其中 \(t=\min(j,c[i])\)

从而得到状态转移方程:
\(f[i][j]=\sum\limits_{s=0}^{\min(j,c[i])}f[i-1][j-s]*C_j^s\)
(解释:\(j\)的长度中,先取出\(s\)个位置放字母\(i\),剩下位置就是字母\(1\sim (i-1)\)组成的长度为\(j\)的字符串了)
初始值:\(f[i][0]=1\)

时间复杂度:\(C\)需要\(O(k^2)\)预处理,dp过程\(O(26*k^2)\)。总时间复杂度\(O(26*k^2)\)
空间复杂度:\(O(k^2+26k)\),但\(f\)可以滚动数组变成\(O(k)\)

Code

非滚动数组
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
int k,c[30],C[1010][1010];
int f[30][1010];
int ans;
signed main(){
	cin>>k;
	for(int i=0;i<=k;i++){
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;j++)
			C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
	}
	for(int i=1;i<=26;i++) cin>>c[i];
	for(int i=0;i<=26;i++) f[i][0]=1;
	for(int i=1;i<=26;i++)
		for(int j=1;j<=k;j++)
			for(int s=0;s<=min(j,c[i]);s++)
				f[i][j]=(f[i][j]+(f[i-1][j-s]*C[j][s]%mod))%mod;
	for(int i=1;i<=k;i++) ans=(ans+f[26][i])%mod;
	cout<<ans;
	return 0;
}
滚动数组
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
int k,c[30],C[1010][1010];
int f[1010];
int ans;
signed main(){
	cin>>k;
	for(int i=0;i<=k;i++){
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;j++)
			C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
	}
	for(int i=1;i<=26;i++) cin>>c[i];
	f[0]=1;
	for(int i=1;i<=26;i++)
		for(int j=k;j>=1;j--)//注意倒序枚举
			for(int s=1;s<=min(j,c[i]);s++)
				//不从0开始是因为已经有值了
				f[j]=(f[j]+(f[j-s]*C[j][s]%mod))%mod;
	for(int i=1;i<=k;i++) ans=(ans+f[i])%mod;
	cout<<ans;
	return 0;
}
posted @ 2024-06-16 11:56  Sinktank  阅读(83)  评论(0编辑  收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2024 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.