现有大写英文字母A-Z,个数分别为C[i],总共可以组成多少个长度在[1,K]之间的不同串?答案对998244353取模。
1<=K<=1000, 0<=C[i]<=1000
分析:记dp[i][k]表示前i类字母构成长度为k的不同方案数,枚举第i类字母的个数j进行转移。
#include <bits/stdc++.h>
using i64 = long long;
template<int MOD>
struct MInt {
i64 x;
int norm(i64 u) const {u%=MOD; if(u<0) u+=MOD; return u;}
MInt(i64 v=0):x(norm(v)) {}
int val() const {return x;}
MInt operator-() const {return MInt(norm(MOD-x));}
MInt inv() const {assert(x!=0); return power(MOD-2);}
MInt &operator*=(const MInt &o) {x=norm(x*o.x); return *this;}
MInt &operator+=(const MInt &o) {x=norm(x+o.x); return *this;}
MInt &operator-=(const MInt &o) {x=norm(x-o.x); return *this;}
MInt &operator/=(const MInt &o) {*this *= o.inv(); return *this;}
friend MInt operator*(const MInt &a, const MInt &b) {MInt ans=a; ans*=b; return ans;}
friend MInt operator+(const MInt &a, const MInt &b) {MInt ans=a; ans+=b; return ans;}
friend MInt operator-(const MInt &a, const MInt &b) {MInt ans=a; ans-=b; return ans;}
friend MInt operator/(const MInt &a, const MInt &b) {MInt ans=a; ans/=b; return ans;}
friend std::istream &operator>>(std::istream &is, MInt &a) {i64 u; is>>u; a=MInt(u); return is;}
friend std::ostream &operator<<(std::ostream &os, const MInt &a) {os<<a.val(); return os;}
MInt power(i64 b) const {i64 r=1, t=x; while(b){if(b&1) r=r*t%MOD; t=t*t%MOD; b/=2;} return MInt(r);}
};
using mint = MInt<998244353>;
std::vector<mint> fac, ifac;
struct Comb {
void init(int n) {
fac.assign(n + 1, 1);
for (int i = 1; i <= n; i++) {
fac[i] = fac[i - 1] * i;
}
ifac.resize(n + 1);
ifac[n] = fac[n].inv();
for (int i = n - 1; i >= 0; i--) {
ifac[i] = ifac[i + 1] * (i + 1);
}
}
int operator()(int n, int k) {
assert(n <= fac.size());
mint ans = fac[n] * ifac[k] * ifac[n - k];
return ans.val();
}
}comb;
void solve() {
int K;
std::cin >> K;
std::vector<int> C(27);
for (int i = 1; i <= 26; i++) {
std::cin >> C[i];
}
std::vector<std::vector<mint>> dp(27, std::vector<mint>(K + 1));
for (int i = 0; i <= 26; i++) {
dp[i][0] = 1;
}
for (int i = 1; i <= 26; i++) {
for (int k = 1; k <= K; k++) {
for (int j = 0; j <= std::min(C[i], k); j++) {
dp[i][k] += dp[i - 1][k - j] * comb(k, j);
}
}
}
mint ans = 0;
for (int k = 1; k <= K; k++) {
ans += dp[26][k];
}
std::cout << ans << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
comb.init(1000);
int t = 1;
while (t--) solve();
return 0;
}
标签:std,Tiles,ifac,int,Alphabet,i64,vector,abc358E,MInt
From: https://www.cnblogs.com/chenfy27/p/18487544