📅  最后修改于: 2023-12-03 15:41:37.691000             🧑  作者: Mango
在某些游戏或者算法问题中,需要计算使用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