Google Kick Start 2018 Round H

Problem A. Big Buttons

题意

定义一种序列,只含有R和B。给出一个目标长度N,和P个非法前缀。问有多少个长度为N的这种序列,不以非法前缀开头。

范围

1≤P≤min(2^N,100)
Small 1≤N≤10
Large 1≤N≤50

分析

所有长度为N的序列个数为$2^N$,但是其中还有一些非法前缀开头的序列,应当删去。
易知,以一个长度为L的非法前缀开头的序列有$2^{N-L}$个。
但是,这P个非法前缀中可能有一些是其它一些的前缀,在这种情况下,不能直接用上面的式子做减法。
举例而言,如果N为4,非法前缀有两个——

RB
RBR

那么,所有以RBR开头的序列都是以RB开头的序列,即我们在删除以RB开头的序列时就删除了以RBR开头的序列。
为了避免这样的前缀造成重复删除某些序列的情况,我们只考虑那些在非法前缀里“比较短”的前缀序列。
具体而言,就是没有任何其它非法前缀是该前缀序列的前缀。
对于这些“比较短”的非法前缀,设其组成集合$S$,那么答案就是——
$$ 2^N - \sum_{s \in S}{2^{N-|s|}} $$
其中$|s|$表示一个非法前缀$s$的长度。

代码

if __name__ == '__main__':
    testCases = int(input())
    for case in range(testCases):
        n, m = input().strip().split()
        n = int(n)
        m = int(m)
        ans = 2**n
        ban = sorted([input().strip() for i in range(m)])
        for index, prefix in enumerate(ban):
            flag = True
            for i in range(index):
                if prefix.startswith(ban[i]):
                    flag = False
            if flag:
                ans -= 2**(n - len(prefix))
        print('Case #{}: {}'.format(case + 1, ans))

猜你喜欢

转载自www.cnblogs.com/you-siki/p/KickStart2018H.html