Submission #45197784


Source Code Expand

# Class 化
DEBUG = 0

class BitDpInfo():
    def __init__(self, base, I, calc_nstate, contribution, leading_zero_consideration, init_state, result_condition):
        self.base = base
        self.I = I
        self.init_state = init_state
        self.result_condition = result_condition
        self.count = [[0] * I for _ in range(2)]
        self.count_next = [[0] * I for _ in range(2)]
        
        self.contribution = contribution
        if contribution is not None:
            self.value = [[0] * I for _ in range(2)]
            self.value_next = [[0] * I for _ in range(2)]
        
        self.calc_nstate = calc_nstate
        if leading_zero_consideration:
            self.moves = [[None] * self.base for _ in range(2)]
            self.leading_zero_consideration = 1
            self.is_starting = 1
        else:
            self.moves = [[None] * self.base for _ in range(1)]
            self.param = self.count[0][0] = 1
            self.is_starting = 1
    
    def bit_dp_from_top(self, target_digit, is_starting):
        L = []
        for exceed, nexceed, l, r in self.bit_dp_from_top_lr(target_digit, is_starting):
            for digit in range(l, r):
                L.append((exceed, nexceed, digit))
        return L
    def bit_dp_from_top_lr(self, target_digit, is_starting):
        # (from, to, l, r) を返す
        # from と to は、今見ている桁から上の部分が N と一致しているかどうかを返す
        #     0: 一致している
        #     1: N より真に小さい
        # 行き先の digit の範囲が [l, r)

        yield (0, 0, max(is_starting, target_digit), target_digit + 1)
        yield (0, 1, is_starting, target_digit)
        yield (1, 1, 0, self.base)
        if self.leading_zero_consideration:
            if is_starting:
                yield (-1, 1, 1, target_digit)
                yield (-1, 0, max(1, target_digit), target_digit + 1)
            else:
                yield (-1, 1, 1, self.base)

    def transition(self, k, target_digit, po):
        if 1:
            for exceed, nexceed, l, r in self.bit_dp_from_top_lr(target_digit, self.is_starting):
                for digit in range(l, r):
                    self.transition_each(exceed, nexceed, k, digit, po)
        else:
            if self.moves[self.is_starting][target_digit] is None:
                self.moves[self.is_starting][target_digit] = self.bit_dp_from_top(target_digit, self.is_starting)
            for exceed, nexceed, digit in self.moves[self.is_starting][target_digit]:
                self.transition_each(exceed, nexceed, k, digit, po)
            
        self.count = self.count_next
        self.count_next = [[0] * I for _ in range(2)]
        if self.contribution is not None:
            self.value = self.value_next
            self.value_next = [[0] * I for _ in range(2)]
        if self.leading_zero_consideration and target_digit:
            self.is_starting = 0
    
    def transition_each(self, ex, nex, k, digit, po):
        c2 = self.count_next[nex]
        if self.contribution is not None:
            v2 = self.value_next[nex]
        
        init_value = 0
        
        if ex < 0:
            # Leading Zero 考慮する場合のみ
            
            ##### 遷移ここから #####
            state = self.init_state
            c = 1
            v = init_value
            nstate = self.calc_nstate(state, digit, k) # <- 遷移先
            c2[nstate] = (c2[nstate] + 1) % P if P else c2[nstate] + 1
            if self.contribution is not None:
                if P:
                    v2[nstate] = (v2[nstate] + v + c * self.contribution(state, digit, k, po)) % P
                else:
                    v2[nstate] += v + c * self.contribution(state, digit, k, po)
            ##### ここまで #####
        else:
            c1 = self.count[ex]
            if self.contribution is not None:
                v1 = self.value[ex]
            ##### 遷移ここから #####
            for state, c in enumerate(c1):
                if not c:
                    continue
                nstate = self.calc_nstate(state, digit, k) # <- 遷移先
                if P:
                    c2[nstate] = (c2[nstate] + c) % P
                else:
                    c2[nstate] += c
                if self.contribution is not None:
                    v = v1[state]
                    v2[nstate] = (v2[nstate] + v + c * self.contribution(state, digit, k, po)) % P
            ##### ここまで #####
    
    def calc(self, N):
        if type(N) == int:
            NN = [int(a) for a in str(N)][::-1]
        elif type(N) == str:
            NN = [int(a) for a in N][::-1]
        else:
            NN = N
        if P:
            po = pow(self.base, len(NN) - 1, P)
            base_inv = pow(self.base, P - 2, P)
        else:
            po = 1
        for k in range(len(NN))[::-1]:
            target_digit = NN[k]
            self.transition(k, target_digit, po)
            if P:
                po = po * base_inv % P
    
    def result(self):
        if self.contribution is None:
            x = self.count
        else:
            x = self.value
        ans = 0
        for i in range(I):
            if self.result_condition(i):
                ans += x[0][i] + x[1][i]
        return ans % P if P else ans
    
    def __str__(self):
        print("sum =", sum(self.value[0]) + sum(self.value[1]))
        return str([self.count, self.value])

if 1:
    # https://atcoder.jp/contests/abc235/tasks/abc235_f
    P = 998244353
    NN = input()
    M = int(input())
    C = [int(a) for a in input().split()]
    I = 1 << M
    mmm = I - 1
    A = [0] * 10
    for i, c in enumerate(C):
        A[c] = 1 << i

    def calc_next_state(state, digit, k):
        return state | A[digit]
    def contribution(state, digit, k, po):
        return digit * po % P
    def result_condition(s):
        return s == mmm
    leading_zero_consideration = 1
    base = 10
    init_state = 0
    bit_dp_info = BitDpInfo(base, I, calc_next_state, contribution, leading_zero_consideration, init_state, result_condition)
    bit_dp_info.calc(NN)
    print(bit_dp_info.result())
elif 0:
    # https://atcoder.jp/contests/abc208/tasks/abc208_e
    N, K = map(int, input().split())
    S = [0]
    D = {0: 0}
    M = 19
    cnt = 1
    for i2 in range(M * 3 + 1):
        c2 = (i2 + 2) // 3
        for i3 in range(M * 2 + 1):
            c3 = (i3 + 1) // 2
            if c2 + c3 > M:
                continue
            for i5 in range(M + 1):
                c5 = i5
                if c2 + c3 + c5 > M:
                    continue
                for i7 in range(M + 1):
                    c7 = i7
                    if c2 + c3 + c5 + c7 > M:
                        continue
                    a = 2 ** i2 * 3 ** i3 * 5 ** i5 * 7 ** i7
                    D[a] = cnt
                    S.append(a)
                    cnt += 1
    if 0:
        print(cnt)
        print("S =", S)
    I = len(S)
    calc_next_state = lambda s, digit, k: D[S[s] * digit]
    contribution = None
    result_condition = lambda s: S[s] <= K
    P = 0
    leading_zero_consideration = 1
    base = 10
    init_state = 1
    bit_dp_info = BitDpInfo(base, I, calc_next_state, contribution, leading_zero_consideration, init_state, result_condition)
    bit_dp_info.calc(N)
    print(bit_dp_info.result())

Submission Info

Submission Time
Task F - Variety of Digits
User Kiri8128
Language PyPy3 (7.3.0)
Score 0
Code Size 7612 Byte
Status TLE
Exec Time 2208 ms
Memory 95736 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 0 / 500
Status
AC × 3
AC × 32
TLE × 2
Set Name Test Cases
Sample sample_01.txt, sample_02.txt, sample_03.txt
All random_01.txt, random_02.txt, random_03.txt, random_04.txt, random_05.txt, random_06.txt, random_07.txt, random_08.txt, random_09.txt, random_10.txt, random_11.txt, random_12.txt, random_13.txt, random_14.txt, random_15.txt, random_16.txt, random_17.txt, random_18.txt, random_19.txt, random_20.txt, random_21.txt, random_22.txt, random_23.txt, random_24.txt, random_25.txt, random_26.txt, random_27.txt, random_28.txt, random_29.txt, random_30.txt, random_31.txt, sample_01.txt, sample_02.txt, sample_03.txt
Case Name Status Exec Time Memory
random_01.txt AC 63 ms 63384 KiB
random_02.txt AC 48 ms 63224 KiB
random_03.txt AC 49 ms 63356 KiB
random_04.txt AC 54 ms 63412 KiB
random_05.txt AC 58 ms 68732 KiB
random_06.txt AC 60 ms 71040 KiB
random_07.txt AC 57 ms 68684 KiB
random_08.txt AC 126 ms 75000 KiB
random_09.txt AC 148 ms 74904 KiB
random_10.txt AC 148 ms 74972 KiB
random_11.txt TLE 2208 ms 94868 KiB
random_12.txt AC 173 ms 74700 KiB
random_13.txt AC 141 ms 75360 KiB
random_14.txt AC 1250 ms 80776 KiB
random_15.txt AC 214 ms 74808 KiB
random_16.txt AC 479 ms 75620 KiB
random_17.txt AC 290 ms 74976 KiB
random_18.txt AC 195 ms 74644 KiB
random_19.txt AC 89 ms 74644 KiB
random_20.txt AC 434 ms 75312 KiB
random_21.txt AC 125 ms 74528 KiB
random_22.txt AC 1048 ms 79800 KiB
random_23.txt AC 158 ms 74724 KiB
random_24.txt AC 131 ms 75056 KiB
random_25.txt AC 209 ms 74628 KiB
random_26.txt AC 204 ms 75548 KiB
random_27.txt AC 573 ms 76636 KiB
random_28.txt TLE 2208 ms 95736 KiB
random_29.txt AC 64 ms 64660 KiB
random_30.txt AC 133 ms 75176 KiB
random_31.txt AC 50 ms 63368 KiB
sample_01.txt AC 48 ms 63400 KiB
sample_02.txt AC 51 ms 63524 KiB
sample_03.txt AC 73 ms 73944 KiB