📜  计算使用1和2连续得分不2的得分方法(1)

📅  最后修改于: 2023-12-03 15:41:37.691000             🧑  作者: Mango

计算使用1和2连续得分不2的得分方法

在某些游戏或者算法问题中,需要计算使用1和2连续得分不2的得分方法。具体来说,就是给定长度为n(n <= 100)的序列,每个位置可以放置1或2,但是相邻的两个1不能超过1个,求这样的序列个数。

思路

对于一个长度为n的序列,我们可以用递推来计算其方案数,即对于第i个位置,如果放置1,那么第i-1个位置只能放置2,否则方案数为a[i-1],如果放置2,那么第i-1个位置既可以放置1也可以放置2,方案数为a[i-2]。最终的答案即为a[n] + a[n-1]。

代码实现
def count_ways(n):
    if n == 1:
        return 1
    if n == 2:
        return 2
    a, b = 1, 2
    for i in range(3, n + 1):
        a, b = b, a + b
    return a + b
示例
print(count_ways(3))  # 3
print(count_ways(4))  # 5
print(count_ways(5))  # 8
性能优化

由于这个序列本质上还是斐波那契数列,因此我们可以使用矩阵快速幂的方法将时间复杂度降为O(logn)。

def matrix_multiply(a, b):
    c = [[0] * len(b[0]) for _ in range(len(a))]
    for i in range(len(a)):
        for j in range(len(b[0])):
            for k in range(len(b)):
                c[i][j] += a[i][k] * b[k][j]
    return c

def matrix_pow(a, n):
    res = [[1 if i == j else 0 for j in range(len(a))] for i in range(len(a))]
    while n > 0:
        if n & 1:
            res = matrix_multiply(res, a)
        a = matrix_multiply(a, a)
        n >>= 1
    return res

def count_ways(n):
    if n == 1:
        return 1
    if n == 2:
        return 2
    a = [[1, 1], [1, 0]]
    res = matrix_pow(a, n - 2)
    return res[0][0] + res[0][1]
示例
print(count_ways(3))  # 3
print(count_ways(4))  # 5
print(count_ways(5))  # 8