白駿11444号:フィボナッチ数6
3661 ワード
問題解決の考え方
この問題を理解するためには,行列の乗算を用いてフィボナッチ数を求める方法を知る必要がある.
対角化でフィボナッチ数列を求める一般項:https://www.youtube.com/watch?v=uX2IsIykLJc
上記のビデオを学習し,実際の解題では対角化の概念を用いる必要はなく,以下の式のみを用いて解く.
この方法はn番目のフィボナッチ数を求める問題において,nが大きい場合に適している.
def matrixMultipli(row1, col1row2, col2, matrix1, matrix2):
result = [[0 for _ in range(col2)] for _ in range(row1)]
for i in range(row1):
for j in range(col2):
for k in range(col1row2):
result[i][j] += matrix1[i][k] * matrix2[k][j]
result[i][j] %= 1000000007
return result
def devideConquer(n, matrix):
if n == 1:
return matrix
tmp = devideConquer(n//2, matrix)
if n % 2 == 0:
return matrixMultipli(2, 2, 2, tmp, tmp)
else:
return matrixMultipli(2, 2, 2, matrixMultipli(2, 2, 2, tmp, tmp), matrix)
n = int(input())
A = [[1, 1], [1, 0]]
if n >= 3:
result = matrixMultipli(2, 2, 1, devideConquer(n-1, A), [[1], [0]])
print(result[0][0]) # 여기선 굳이 나머지 연산 필요 X (<-> 행렬제곱 문제)
else:
print(1)
def matrixMultipli(row1, col1row2, col2, matrix1, matrix2):
result = [[0 for _ in range(col2)] for _ in range(row1)]
for i in range(row1):
for j in range(col2):
for k in range(col1row2):
result[i][j] += matrix1[i][k] * matrix2[k][j]
result[i][j] %= 1000000007
return result
2つのマトリクスを乗算するために、マトリクス1のcolumnとマトリクス2のrowは同じでなければならない.また、乗算結果に対応する行列は、行列1の行と行列2の列とを有する.行列の乗算により,上図のように三重for文を用いて実現すればよい.10,000,000,000,000,000,000,000で除算された残りの値を求めるため、%演算子を使用して2 D配列に入れます.
n = int(input())
A = [[1, 1], [1, 0]]
result = matrixMultipli(2, 2, 1, devideConquer(n-1, A), [[1], [0]])
print(result[0][0]) # 여기선 굳이 나머지 연산 필요 X (<-> 행렬제곱 문제)
以上の式から,n番目のフィボナッチ数,すなわちF nを求めるためには,[[1,1],[1,0]行列にn−1次方程式を乗じる必要があることが分かる.また、その結果に[1],[0]を乗じなければならない.そこで,まずDevideConquer関数を用いてA行列をn−1反復(以下,パーティション征服の実装について論じる)し,次に[1],[0]行列を乗じる.
演算の結果行列では,F nはrow 0,column 0にあり,結果[0][0]を出力すればよい.コード全体のように、n<3であれば、単独で処理することも忘れないでください.
def devideConquer(n, matrix):
if n == 1:
return matrix
tmp = devideConquer(n//2, matrix)
if n % 2 == 0:
return matrixMultipli(2, 2, 2, tmp, tmp)
else:
return matrixMultipli(2, 2, 2, matrixMultipli(2, 2, 2, tmp, tmp), matrix)
再帰的に自分を呼び出し,n回にマトリクスを乗じた関数.直接実現した行列の乗算関数のみを用いたため,構造自体は以前に解いた問題と同じであるため,説明を省略する.Reference
この問題について(白駿11444号:フィボナッチ数6), 我々は、より多くの情報をここで見つけました https://velog.io/@dlehdtjq00/백준-11444번-피보나치-수-6テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol