Numpy很难使用,因为它适用于固定大小的整数,例如
int32
或
int64
(这里使用哪一个取决于您的python安装)。像这样对矩阵进行指数化会使条目大于该数据类型的限制,从而导致截断。
对于常规Python整数,可以使用这种实现(先乘以矩阵,然后应用模约简),因为常规Python整数可以有更高的值。例如:
def mm(A, B):
return [[sum([x*y for (x, y) in zip(row, col)]) for col in zip(*B)] for row in A]
def knightDialer(N: int) -> int:
M = [[0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 0, 1, 0, 0, 0, 1, 0],
[1, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 1, 0, 0, 0, 0, 0]]
N = N - 1
res = [[int(i == j) for j in range(len(M))] for i in range(len(M))]
while N:
if N & 1: res = mm(res, M)
M = mm(M, M)
N >>= 1
print(M)
return sum([sum(i) for i in zip(*res)]) % (10**9 + 7)
在求幂过程中应用模约简可以让numpy矩阵在不耗尽比特的情况下工作:
def knightDialer(N: int) -> int:
M = np.matrix([[0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 0, 1, 0, 0, 0, 1, 0],
[1, 0, 0, 1, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 1, 0, 0, 0, 0, 0]], dtype=np.int64)
N = N - 1
res = np.eye(M.shape[0], dtype=np.int64)
while N:
if N & 1: res = res * M % (10**9 + 7)
M = M * M % (10**9 + 7)
N >>= 1
return np.sum(res) % (10**9 + 7)
使用
dtype=np.int64
如果安装时默认整数类型为
int32
.
int32
足够容纳以下数字
10**9 + 7
,但在矩阵乘法过程中,两个这样的数字之间会有乘积(然后它们也会被求和),如果
int32
被使用。