chenfy27的刷题记录

导航

abc358E Alphabet Tiles

现有大写英文字母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;
}

posted on 2024-10-20 17:37  chenfy27  阅读(18)  评论(0)    收藏  举报