結果

問題 No.2388 At Least K-Characters
コンテスト
ユーザー norioc
提出日時 2026-01-08 19:59:39
言語 PyPy3
(7.3.17)
結果
WA  
実行時間 -
コード長 3,007 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 273 ms
コンパイル使用メモリ 82,348 KB
実行使用メモリ 125,248 KB
最終ジャッジ日時 2026-01-08 19:59:48
合計ジャッジ時間 7,236 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2 WA * 1
other AC * 7 WA * 6 TLE * 1 -- * 20
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

from collections.abc import Iterable


def accum_dp(xs: Iterable, f, op, e, init: dict, *, is_reset=True):
    dp = init.copy()
    for x in xs:
        pp = {} if is_reset else dp.copy()
        dp, pp = pp, dp
        for fm_key, fm_val in pp.items():
            for to_key, to_val in f(fm_key, fm_val, x):
                dp[to_key] = op(dp.get(to_key, e), to_val)

    return dp


def f(k, v, x):
    global ans
    m, lt = k  # (使った文字種, 未満か)
    p = x

    if lt:
        # 使った文字を末尾に置く
        yield (m, True), v * m
        if m < 26:
            # 未使用の文字を末尾に置く
            yield (m+1, True), v * (26 - m)

        if m >= K:
            ans += v * m
        if m < 26 and m+1 >= K:
            ans += v * (26 - m)
        ans %= MOD
    elif p == 0:
        nm = 1
        cnt = ds[p]  # より小さい文字
        if cnt > 0:
            yield (nm, True), cnt
            if K == 1:
                ans += cnt
                ans %= MOD

        yield (0, False), 1  # not lt を維持

        if K == 1 and p+1 < N:  # 先頭p文字が S に一致する部分列の分
            ans += 1
            ans %= MOD
    elif p < N:
        used = used_masks[p-1]  # 使ったビット
        used_less = used & ((1 << max(0, ds[p]-1)) - 1)  # 使ったビット(いま見ている文字より小さい)

        used_cnt = used.bit_count()
        used_less_cnt = used_less.bit_count()
        if used_less_cnt > 0:  # 使ったビットから選ぶ(より小さい文字)
            yield (used_cnt, True), v * used_less_cnt

            if used_cnt >= K:
                ans += v * used_less_cnt
                ans %= MOD

        # 使っていないビットから選ぶ(より小さい文字)
        unused_less_cnt = ds[p] - used_less_cnt
        if unused_less_cnt > 0:
            yield (used_cnt+1, True), v * unused_less_cnt

            if used_cnt+1 >= K:
                ans += v * unused_less_cnt
                ans %= MOD

        # # 文字 x より小さい文字を置く
        # for i in range(26):
        #     if i >= cs[p]: break
        #     if p == 0:
        #         nm = 0
        #         b = 0
        #     else:
        #         nm, b = kinds[p-1]
        #     if not (b & (1 << i)):
        #         nm += 1
        #     yield (nm, True), v
        #
        #     if nm >= K:
        #         ans += v
        #         ans %= MOD

        if p+1 < N and used_masks[p].bit_count() >= K:
            ans += 1
            ans %= MOD

        # not lt を維持
        yield (0, False), v


def op(a, b):
    return (a + b) % MOD


def digit_dp():
    init = {(0, False): 1}
    accum_dp(range(M), f, op, 0, init)


MOD = 998244353
N, M, K = map(int, input().split())
S = input()

ds = [ord(c) - ord('a') for c in S]
b = 0
used_masks = []  # i 番目までで使われている文字種(ビット)
for d in ds:
    b |= (1 << d)
    used_masks.append(b)

ans = 0
digit_dp()
print(ans)
0