[{"data":1,"prerenderedAt":1402},["ShallowReactive",2],{"content-/fibonacci-millionth":3,"all-pages-for-dir":1379,"related-/fibonacci-millionth":1380,"og-image-/fibonacci-millionth":1401},{"id":4,"title":5,"body":6,"category":1365,"concepts":1365,"description":1366,"extension":1367,"meta":1368,"navigation":473,"ogImage":1365,"path":1369,"project_name":1365,"published":1370,"publishedAt":1371,"seo":1372,"source":1365,"stem":1373,"tags":1374,"todo":1365,"unpublished":1370,"updatedAt":1371,"__hash__":1378},"pages/2025-12/2025-12-19/fibonacci-millionth.md","フィボナッチ数列100万番目を求めるアプローチ",{"type":7,"value":8,"toc":1351},"minimark",[9,12,16,20,136,165,168,171,178,181,187,195,718,729,733,736,742,748,982,985,989,992,1009,1084,1092,1112,1115,1118,1124,1138,1141,1196,1199,1202,1207,1219,1223,1238,1242,1258,1262,1296,1299,1344,1347],[10,11,5],"h1",{"id":5},[13,14,15],"h2",{"id":15},"素朴な実装の限界",[17,18,19],"p",{},"まず、単純なループで考える。",[21,22,27],"pre",{"className":23,"code":24,"language":25,"meta":26,"style":26},"language-python shiki shiki-themes vitesse-light vitesse-light","def fib_naive(n):\n    a, b = 0, 1\n    for _ in range(n):\n        a, b = b, a + b\n    return a\n","python","",[28,29,30,54,78,101,127],"code",{"__ignoreMap":26},[31,32,35,39,43,47,51],"span",{"class":33,"line":34},"line",1,[31,36,38],{"class":37},"stQ0i","def",[31,40,42],{"class":41},"senZ8"," fib_naive",[31,44,46],{"class":45},"shFtX","(",[31,48,50],{"class":49},"sG7-3","n",[31,52,53],{"class":45},"):\n",[31,55,57,60,63,66,69,73,75],{"class":33,"line":56},2,[31,58,59],{"class":49},"    a",[31,61,62],{"class":45},",",[31,64,65],{"class":49}," b ",[31,67,68],{"class":45},"=",[31,70,72],{"class":71},"sM54T"," 0",[31,74,62],{"class":45},[31,76,77],{"class":71}," 1\n",[31,79,81,85,88,91,95,97,99],{"class":33,"line":80},3,[31,82,84],{"class":83},"sHkkW","    for",[31,86,87],{"class":49}," _ ",[31,89,90],{"class":83},"in",[31,92,94],{"class":93},"sz8Xr"," range",[31,96,46],{"class":45},[31,98,50],{"class":49},[31,100,53],{"class":45},[31,102,104,107,109,111,113,116,118,121,124],{"class":33,"line":103},4,[31,105,106],{"class":49},"        a",[31,108,62],{"class":45},[31,110,65],{"class":49},[31,112,68],{"class":45},[31,114,115],{"class":49}," b",[31,117,62],{"class":45},[31,119,120],{"class":49}," a ",[31,122,123],{"class":37},"+",[31,125,126],{"class":49}," b\n",[31,128,130,133],{"class":33,"line":129},5,[31,131,132],{"class":83},"    return",[31,134,135],{"class":49}," a\n",[17,137,138,144,145,149,150,154,155,159,160,164],{},[28,139,143],{"className":140},[141,142],"language-math","math-inline","n = 10^6"," の場合、ループ自体は100万回で終わる。ただし問題は",[146,147,148],"strong",{},"多倍長整数の加算コスト","である。",[28,151,153],{"className":152},[141,142],"F_{10^6}"," は約20万桁になるため、加算1回が ",[28,156,158],{"className":157},[141,142],"O(\\text{桁数})"," かかる。結果的に ",[28,161,163],{"className":162},[141,142],"O(n \\cdot \\text{桁数})"," となり、実測で数十秒〜数分オーダー。",[13,166,167],{"id":167},"行列累乗法",[17,169,170],{},"フィボナッチの漸化式を行列で表現：",[21,172,173],{},[28,174,177],{"className":175},[141,176],"math-display","\\begin{pmatrix} F_{n+1} \\\\ F_n \\end{pmatrix} = \\begin{pmatrix} 1 & 1 \\\\ 1 & 0 \\end{pmatrix} \\begin{pmatrix} F_n \\\\ F_{n-1} \\end{pmatrix}",[17,179,180],{},"これを展開すると：",[21,182,183],{},[28,184,186],{"className":185},[141,176],"\\begin{pmatrix} F_{n+1} \\\\ F_n \\end{pmatrix} = \\begin{pmatrix} 1 & 1 \\\\ 1 & 0 \\end{pmatrix}^n \\begin{pmatrix} 1 \\\\ 0 \\end{pmatrix}",[17,188,189,190,194],{},"行列の累乗は繰り返し二乗法で ",[28,191,193],{"className":192},[141,142],"O(\\log n)"," 回の行列乗算で計算可能。",[21,196,198],{"className":23,"code":197,"language":25,"meta":26,"style":26},"def matrix_mult(A, B):\n    return [\n        [A[0][0]*B[0][0] + A[0][1]*B[1][0], A[0][0]*B[0][1] + A[0][1]*B[1][1]],\n        [A[1][0]*B[0][0] + A[1][1]*B[1][0], A[1][0]*B[0][1] + A[1][1]*B[1][1]]\n    ]\n\ndef matrix_pow(M, n):\n    result = [[1, 0], [0, 1]]  # 単位行列\n    while n:\n        if n & 1:\n            result = matrix_mult(result, M)\n        M = matrix_mult(M, M)\n        n >>= 1\n    return result\n\ndef fib_matrix(n):\n    if n == 0:\n        return 0\n    M = [[1, 1], [1, 0]]\n    return matrix_pow(M, n)[0][1]\n",[28,199,200,219,226,350,463,468,475,495,531,542,558,581,601,612,620,625,639,654,663,691],{"__ignoreMap":26},[31,201,202,204,207,209,212,214,217],{"class":33,"line":34},[31,203,38],{"class":37},[31,205,206],{"class":41}," matrix_mult",[31,208,46],{"class":45},[31,210,211],{"class":49},"A",[31,213,62],{"class":45},[31,215,216],{"class":49}," B",[31,218,53],{"class":45},[31,220,221,223],{"class":33,"line":56},[31,222,132],{"class":83},[31,224,225],{"class":45}," [\n",[31,227,228,231,233,236,239,242,244,247,250,253,255,257,259,261,263,266,269,271,273,275,278,280,282,284,286,288,290,292,295,297,299,301,303,305,307,309,311,313,315,317,319,321,323,325,327,329,331,333,335,337,339,341,343,345,347],{"class":33,"line":80},[31,229,230],{"class":45},"        [",[31,232,211],{"class":49},[31,234,235],{"class":45},"[",[31,237,238],{"class":71},"0",[31,240,241],{"class":45},"][",[31,243,238],{"class":71},[31,245,246],{"class":45},"]",[31,248,249],{"class":37},"*",[31,251,252],{"class":49},"B",[31,254,235],{"class":45},[31,256,238],{"class":71},[31,258,241],{"class":45},[31,260,238],{"class":71},[31,262,246],{"class":45},[31,264,265],{"class":37}," +",[31,267,268],{"class":49}," A",[31,270,235],{"class":45},[31,272,238],{"class":71},[31,274,241],{"class":45},[31,276,277],{"class":71},"1",[31,279,246],{"class":45},[31,281,249],{"class":37},[31,283,252],{"class":49},[31,285,235],{"class":45},[31,287,277],{"class":71},[31,289,241],{"class":45},[31,291,238],{"class":71},[31,293,294],{"class":45},"],",[31,296,268],{"class":49},[31,298,235],{"class":45},[31,300,238],{"class":71},[31,302,241],{"class":45},[31,304,238],{"class":71},[31,306,246],{"class":45},[31,308,249],{"class":37},[31,310,252],{"class":49},[31,312,235],{"class":45},[31,314,238],{"class":71},[31,316,241],{"class":45},[31,318,277],{"class":71},[31,320,246],{"class":45},[31,322,265],{"class":37},[31,324,268],{"class":49},[31,326,235],{"class":45},[31,328,238],{"class":71},[31,330,241],{"class":45},[31,332,277],{"class":71},[31,334,246],{"class":45},[31,336,249],{"class":37},[31,338,252],{"class":49},[31,340,235],{"class":45},[31,342,277],{"class":71},[31,344,241],{"class":45},[31,346,277],{"class":71},[31,348,349],{"class":45},"]],\n",[31,351,352,354,356,358,360,362,364,366,368,370,372,374,376,378,380,382,384,386,388,390,392,394,396,398,400,402,404,406,408,410,412,414,416,418,420,422,424,426,428,430,432,434,436,438,440,442,444,446,448,450,452,454,456,458,460],{"class":33,"line":103},[31,353,230],{"class":45},[31,355,211],{"class":49},[31,357,235],{"class":45},[31,359,277],{"class":71},[31,361,241],{"class":45},[31,363,238],{"class":71},[31,365,246],{"class":45},[31,367,249],{"class":37},[31,369,252],{"class":49},[31,371,235],{"class":45},[31,373,238],{"class":71},[31,375,241],{"class":45},[31,377,238],{"class":71},[31,379,246],{"class":45},[31,381,265],{"class":37},[31,383,268],{"class":49},[31,385,235],{"class":45},[31,387,277],{"class":71},[31,389,241],{"class":45},[31,391,277],{"class":71},[31,393,246],{"class":45},[31,395,249],{"class":37},[31,397,252],{"class":49},[31,399,235],{"class":45},[31,401,277],{"class":71},[31,403,241],{"class":45},[31,405,238],{"class":71},[31,407,294],{"class":45},[31,409,268],{"class":49},[31,411,235],{"class":45},[31,413,277],{"class":71},[31,415,241],{"class":45},[31,417,238],{"class":71},[31,419,246],{"class":45},[31,421,249],{"class":37},[31,423,252],{"class":49},[31,425,235],{"class":45},[31,427,238],{"class":71},[31,429,241],{"class":45},[31,431,277],{"class":71},[31,433,246],{"class":45},[31,435,265],{"class":37},[31,437,268],{"class":49},[31,439,235],{"class":45},[31,441,277],{"class":71},[31,443,241],{"class":45},[31,445,277],{"class":71},[31,447,246],{"class":45},[31,449,249],{"class":37},[31,451,252],{"class":49},[31,453,235],{"class":45},[31,455,277],{"class":71},[31,457,241],{"class":45},[31,459,277],{"class":71},[31,461,462],{"class":45},"]]\n",[31,464,465],{"class":33,"line":129},[31,466,467],{"class":45},"    ]\n",[31,469,471],{"class":33,"line":470},6,[31,472,474],{"emptyLinePlaceholder":473},true,"\n",[31,476,478,480,483,485,488,490,493],{"class":33,"line":477},7,[31,479,38],{"class":37},[31,481,482],{"class":41}," matrix_pow",[31,484,46],{"class":45},[31,486,487],{"class":49},"M",[31,489,62],{"class":45},[31,491,492],{"class":49}," n",[31,494,53],{"class":45},[31,496,498,501,503,506,508,510,512,514,517,519,521,524,527],{"class":33,"line":497},8,[31,499,500],{"class":49},"    result ",[31,502,68],{"class":45},[31,504,505],{"class":45}," [[",[31,507,277],{"class":71},[31,509,62],{"class":45},[31,511,72],{"class":71},[31,513,294],{"class":45},[31,515,516],{"class":45}," [",[31,518,238],{"class":71},[31,520,62],{"class":45},[31,522,523],{"class":71}," 1",[31,525,526],{"class":45},"]]",[31,528,530],{"class":529},"sxvE3","  # 単位行列\n",[31,532,534,537,539],{"class":33,"line":533},9,[31,535,536],{"class":83},"    while",[31,538,492],{"class":49},[31,540,541],{"class":45},":\n",[31,543,545,548,551,554,556],{"class":33,"line":544},10,[31,546,547],{"class":83},"        if",[31,549,550],{"class":49}," n ",[31,552,553],{"class":37},"&",[31,555,523],{"class":71},[31,557,541],{"class":45},[31,559,561,564,566,568,570,573,575,578],{"class":33,"line":560},11,[31,562,563],{"class":49},"            result ",[31,565,68],{"class":45},[31,567,206],{"class":49},[31,569,46],{"class":45},[31,571,572],{"class":49},"result",[31,574,62],{"class":45},[31,576,577],{"class":49}," M",[31,579,580],{"class":45},")\n",[31,582,584,587,589,591,593,595,597,599],{"class":33,"line":583},12,[31,585,586],{"class":49},"        M ",[31,588,68],{"class":45},[31,590,206],{"class":49},[31,592,46],{"class":45},[31,594,487],{"class":49},[31,596,62],{"class":45},[31,598,577],{"class":49},[31,600,580],{"class":45},[31,602,604,607,610],{"class":33,"line":603},13,[31,605,606],{"class":49},"        n ",[31,608,609],{"class":45},">>=",[31,611,77],{"class":71},[31,613,615,617],{"class":33,"line":614},14,[31,616,132],{"class":83},[31,618,619],{"class":49}," result\n",[31,621,623],{"class":33,"line":622},15,[31,624,474],{"emptyLinePlaceholder":473},[31,626,628,630,633,635,637],{"class":33,"line":627},16,[31,629,38],{"class":37},[31,631,632],{"class":41}," fib_matrix",[31,634,46],{"class":45},[31,636,50],{"class":49},[31,638,53],{"class":45},[31,640,642,645,647,650,652],{"class":33,"line":641},17,[31,643,644],{"class":83},"    if",[31,646,550],{"class":49},[31,648,649],{"class":37},"==",[31,651,72],{"class":71},[31,653,541],{"class":45},[31,655,657,660],{"class":33,"line":656},18,[31,658,659],{"class":83},"        return",[31,661,662],{"class":71}," 0\n",[31,664,666,669,671,673,675,677,679,681,683,685,687,689],{"class":33,"line":665},19,[31,667,668],{"class":49},"    M ",[31,670,68],{"class":45},[31,672,505],{"class":45},[31,674,277],{"class":71},[31,676,62],{"class":45},[31,678,523],{"class":71},[31,680,294],{"class":45},[31,682,516],{"class":45},[31,684,277],{"class":71},[31,686,62],{"class":45},[31,688,72],{"class":71},[31,690,462],{"class":45},[31,692,694,696,698,700,702,704,706,709,711,713,715],{"class":33,"line":693},20,[31,695,132],{"class":83},[31,697,482],{"class":49},[31,699,46],{"class":45},[31,701,487],{"class":49},[31,703,62],{"class":45},[31,705,492],{"class":49},[31,707,708],{"class":45},")[",[31,710,238],{"class":71},[31,712,241],{"class":45},[31,714,277],{"class":71},[31,716,717],{"class":45},"]\n",[17,719,720,721,724,725,728],{},"計算量は ",[28,722,193],{"className":723},[141,142]," 回の行列乗算。ただし各要素が巨大整数なので、乗算コストを考慮すると単純な ",[28,726,193],{"className":727},[141,142]," ではない。",[13,730,732],{"id":731},"高速倍化法fast-doubling","高速倍化法（Fast Doubling）",[17,734,735],{},"行列累乗から導出される以下の恒等式を直接使う：",[21,737,738],{},[28,739,741],{"className":740},[141,176],"F_{2k} = F_k \\cdot (2F_{k+1} - F_k)",[21,743,744],{},[28,745,747],{"className":746},[141,176],"F_{2k+1} = F_k^2 + F_{k+1}^2",[21,749,751],{"className":23,"code":750,"language":25,"meta":26,"style":26},"def fib_fast_doubling(n):\n    def fib_pair(n):\n        \"\"\"(F_n, F_{n+1}) を返す\"\"\"\n        if n == 0:\n            return (0, 1)\n\n        f_k, f_k1 = fib_pair(n >> 1)\n        f_2k = f_k * (2 * f_k1 - f_k)\n        f_2k1 = f_k * f_k + f_k1 * f_k1\n\n        if n & 1:\n            return (f_2k1, f_2k + f_2k1)\n        else:\n            return (f_2k, f_2k1)\n\n    return fib_pair(n)[0]\n",[28,752,753,766,780,793,805,821,825,851,881,903,907,919,940,947,962,966],{"__ignoreMap":26},[31,754,755,757,760,762,764],{"class":33,"line":34},[31,756,38],{"class":37},[31,758,759],{"class":41}," fib_fast_doubling",[31,761,46],{"class":45},[31,763,50],{"class":49},[31,765,53],{"class":45},[31,767,768,771,774,776,778],{"class":33,"line":56},[31,769,770],{"class":37},"    def",[31,772,773],{"class":41}," fib_pair",[31,775,46],{"class":45},[31,777,50],{"class":49},[31,779,53],{"class":45},[31,781,782,786,790],{"class":33,"line":80},[31,783,785],{"class":784},"sMJiu","        \"\"\"",[31,787,789],{"class":788},"sdGka","(F_n, F_{n+1}) を返す",[31,791,792],{"class":784},"\"\"\"\n",[31,794,795,797,799,801,803],{"class":33,"line":103},[31,796,547],{"class":83},[31,798,550],{"class":49},[31,800,649],{"class":37},[31,802,72],{"class":71},[31,804,541],{"class":45},[31,806,807,810,813,815,817,819],{"class":33,"line":129},[31,808,809],{"class":83},"            return",[31,811,812],{"class":45}," (",[31,814,238],{"class":71},[31,816,62],{"class":45},[31,818,523],{"class":71},[31,820,580],{"class":45},[31,822,823],{"class":33,"line":470},[31,824,474],{"emptyLinePlaceholder":473},[31,826,827,830,832,835,837,839,841,844,847,849],{"class":33,"line":477},[31,828,829],{"class":49},"        f_k",[31,831,62],{"class":45},[31,833,834],{"class":49}," f_k1 ",[31,836,68],{"class":45},[31,838,773],{"class":49},[31,840,46],{"class":45},[31,842,843],{"class":49},"n ",[31,845,846],{"class":37},">>",[31,848,523],{"class":71},[31,850,580],{"class":45},[31,852,853,856,858,861,863,865,868,871,873,876,879],{"class":33,"line":497},[31,854,855],{"class":49},"        f_2k ",[31,857,68],{"class":45},[31,859,860],{"class":49}," f_k ",[31,862,249],{"class":37},[31,864,812],{"class":45},[31,866,867],{"class":71},"2",[31,869,870],{"class":37}," *",[31,872,834],{"class":49},[31,874,875],{"class":37},"-",[31,877,878],{"class":49}," f_k",[31,880,580],{"class":45},[31,882,883,886,888,890,892,894,896,898,900],{"class":33,"line":533},[31,884,885],{"class":49},"        f_2k1 ",[31,887,68],{"class":45},[31,889,860],{"class":49},[31,891,249],{"class":37},[31,893,860],{"class":49},[31,895,123],{"class":37},[31,897,834],{"class":49},[31,899,249],{"class":37},[31,901,902],{"class":49}," f_k1\n",[31,904,905],{"class":33,"line":544},[31,906,474],{"emptyLinePlaceholder":473},[31,908,909,911,913,915,917],{"class":33,"line":560},[31,910,547],{"class":83},[31,912,550],{"class":49},[31,914,553],{"class":37},[31,916,523],{"class":71},[31,918,541],{"class":45},[31,920,921,923,925,928,930,933,935,938],{"class":33,"line":583},[31,922,809],{"class":83},[31,924,812],{"class":45},[31,926,927],{"class":49},"f_2k1",[31,929,62],{"class":45},[31,931,932],{"class":49}," f_2k ",[31,934,123],{"class":37},[31,936,937],{"class":49}," f_2k1",[31,939,580],{"class":45},[31,941,942,945],{"class":33,"line":603},[31,943,944],{"class":83},"        else",[31,946,541],{"class":45},[31,948,949,951,953,956,958,960],{"class":33,"line":614},[31,950,809],{"class":83},[31,952,812],{"class":45},[31,954,955],{"class":49},"f_2k",[31,957,62],{"class":45},[31,959,937],{"class":49},[31,961,580],{"class":45},[31,963,964],{"class":33,"line":622},[31,965,474],{"emptyLinePlaceholder":473},[31,967,968,970,972,974,976,978,980],{"class":33,"line":627},[31,969,132],{"class":83},[31,971,773],{"class":49},[31,973,46],{"class":45},[31,975,50],{"class":49},[31,977,708],{"class":45},[31,979,238],{"class":71},[31,981,717],{"class":45},[17,983,984],{},"2x2行列の4要素ではなく2要素だけ追跡するため、行列累乗と本質的に同じだが定数倍で有利である。",[986,987],"drawio-viewer",{"src":988},"/2025-12-19/fibonacci-fast-doubling.drawio",[13,990,991],{"id":991},"計算量の詳細分析",[17,993,994,998,999,1003,1004,1008],{},[28,995,997],{"className":996},[141,142],"F_n"," の桁数は ",[28,1000,1002],{"className":1001},[141,142],"O(n)"," である（",[28,1005,1007],{"className":1006},[141,142],"F_n \\approx \\phi^n / \\sqrt{5}"," より）。",[1010,1011,1012,1028],"table",{},[1013,1014,1015],"thead",{},[1016,1017,1018,1022,1025],"tr",{},[1019,1020,1021],"th",{},"手法",[1019,1023,1024],{},"乗算/加算回数",[1019,1026,1027],{},"多倍長乗算コスト込み",[1029,1030,1031,1053,1069],"tbody",{},[1016,1032,1033,1037,1042],{},[1034,1035,1036],"td",{},"素朴ループ",[1034,1038,1039],{},[28,1040,1002],{"className":1041},[141,142],[1034,1043,1044,1048,1049,249],{},[28,1045,1047],{"className":1046},[141,142],"O(n^2)"," ～ ",[28,1050,1052],{"className":1051},[141,142],"O(n^2 / \\log n)",[1016,1054,1055,1058,1063],{},[1034,1056,1057],{},"行列累乗",[1034,1059,1060],{},[28,1061,193],{"className":1062},[141,142],[1034,1064,1065],{},[28,1066,1068],{"className":1067},[141,142],"O(M(n) \\log n)",[1016,1070,1071,1074,1079],{},[1034,1072,1073],{},"Fast Doubling",[1034,1075,1076],{},[28,1077,193],{"className":1078},[141,142],[1034,1080,1081],{},[28,1082,1068],{"className":1083},[141,142],[17,1085,1086,1087,1091],{},"*Pythonの多倍長整数はKaratsuba法を使うため、乗算は ",[28,1088,1090],{"className":1089},[141,142],"O(n^{1.585})"," 程度。",[17,1093,1094,1098,1099,1102,1103,1106,1107,1111],{},[28,1095,1097],{"className":1096},[141,142],"M(n)"," は ",[28,1100,50],{"className":1101},[141,142]," 桁の乗算コスト。Karatsuba なら ",[28,1104,1090],{"className":1105},[141,142],"、FFT系なら ",[28,1108,1110],{"className":1109},[141,142],"O(n \\log n)"," 近辺。",[986,1113],{"src":1114},"/2025-12-19/fibonacci-complexity.drawio",[13,1116,1117],{"id":1117},"実測値の目安",[17,1119,1120,1123],{},[28,1121,143],{"className":1122},[141,142]," の場合（Python 3、一般的なPC）：",[1125,1126,1127,1133],"ul",{},[1128,1129,1130,1132],"li",{},[146,1131,1036],{},": 30〜60秒",[1128,1134,1135,1137],{},[146,1136,1073],{},": 1〜3秒",[17,1139,1140],{},"約20倍以上の高速化。GMP（gmpy2）を使えばさらに高速。",[21,1142,1144],{"className":23,"code":1143,"language":25,"meta":26,"style":26},"import gmpy2\n\ndef fib_gmpy(n):\n    return int(gmpy2.fib(n))\n",[28,1145,1146,1154,1158,1171],{"__ignoreMap":26},[31,1147,1148,1151],{"class":33,"line":34},[31,1149,1150],{"class":83},"import",[31,1152,1153],{"class":49}," gmpy2\n",[31,1155,1156],{"class":33,"line":56},[31,1157,474],{"emptyLinePlaceholder":473},[31,1159,1160,1162,1165,1167,1169],{"class":33,"line":80},[31,1161,38],{"class":37},[31,1163,1164],{"class":41}," fib_gmpy",[31,1166,46],{"class":45},[31,1168,50],{"class":49},[31,1170,53],{"class":45},[31,1172,1173,1175,1178,1180,1183,1186,1189,1191,1193],{"class":33,"line":103},[31,1174,132],{"class":83},[31,1176,1177],{"class":93}," int",[31,1179,46],{"class":45},[31,1181,1182],{"class":49},"gmpy2",[31,1184,1185],{"class":45},".",[31,1187,1188],{"class":49},"fib",[31,1190,46],{"class":45},[31,1192,50],{"class":49},[31,1194,1195],{"class":45},"))\n",[17,1197,1198],{},"gmpy2は内部で最適化されたアルゴリズムを使用しており、100万番目でも1秒未満。",[13,1200,1201],{"id":1201},"面接での補足ポイント",[1203,1204,1206],"h3",{"id":1205},"なぜ行列累乗が速いのかへの回答","「なぜ行列累乗が速いのか」への回答",[17,1208,1209,1210,1213,1214,1218],{},"素朴な方法は",[28,1211,50],{"className":1212},[141,142],"回の加算を逐次実行する。行列累乗は「倍々で進む」ことで",[28,1215,1217],{"className":1216},[141,142],"\\log n","ステップに圧縮する。各ステップでの計算量は増えるが、ステップ数の削減効果が圧倒的である。",[1203,1220,1222],{"id":1221},"メモ化再帰との比較は","「メモ化再帰との比較は？」",[17,1224,1225,1226,1229,1230,1233,1234,1237],{},"メモ化再帰は",[28,1227,1002],{"className":1228},[141,142],"のメモリを消費し、かつ",[28,1231,1002],{"className":1232},[141,142],"回の加算が必要である。Fast Doublingは",[28,1235,193],{"className":1236},[141,142],"のスタック深さで済む。",[1203,1239,1241],{"id":1240},"mod-を取る場合は","「mod を取る場合は？」",[17,1243,1244,1248,1249,1253,1254,1257],{},[28,1245,1247],{"className":1246},[141,142],"F_n \\mod m","を求める場合、行列累乗/Fast Doublingがそのまま適用可能である。各演算後にmodを取れば、整数サイズが",[28,1250,1252],{"className":1251},[141,142],"O(\\log m)","に抑えられ、純粋に",[28,1255,193],{"className":1256},[141,142],"となる。競プロでよく出るパターンである。",[1203,1259,1261],{"id":1260},"周期性ピサノ周期は使える","「周期性（ピサノ周期）は使える？」",[17,1263,1264,1267,1268,1272,1273,1277,1278,1282,1283,1286,1287,1291,1292,1295],{},[28,1265,1247],{"className":1266},[141,142],"には周期",[28,1269,1271],{"className":1270},[141,142],"\\pi(m)","が存在する。",[28,1274,1276],{"className":1275},[141,142],"m","が小さければ周期を求めてから",[28,1279,1281],{"className":1280},[141,142],"n \\mod \\pi(m)","で計算すると速い。ただし",[28,1284,1271],{"className":1285},[141,142],"の上界は",[28,1288,1290],{"className":1289},[141,142],"6m","なので、",[28,1293,1276],{"className":1294},[141,142],"が大きいと周期探索自体がコストになる。",[13,1297,1298],{"id":1298},"まとめ",[1010,1300,1301,1311],{},[1013,1302,1303],{},[1016,1304,1305,1308],{},[1019,1306,1307],{},"観点",[1019,1309,1310],{},"推奨",[1029,1312,1313,1320,1328,1336],{},[1016,1314,1315,1318],{},[1034,1316,1317],{},"実装のシンプルさ",[1034,1319,1073],{},[1016,1321,1322,1325],{},[1034,1323,1324],{},"最速",[1034,1326,1327],{},"gmpy2.fib()",[1016,1329,1330,1333],{},[1034,1331,1332],{},"mod付き",[1034,1334,1335],{},"Fast Doubling + mod",[1016,1337,1338,1341],{},[1034,1339,1340],{},"面接での説明",[1034,1342,1343],{},"行列累乗の導出 → Fast Doublingへの簡略化",[17,1345,1346],{},"100万番目程度であればFast Doublingで十分実用的である。それ以上（10億など）になると、SchönhageーStrassen法などさらに高度な多倍長演算の最適化が効いてくる。",[1348,1349,1350],"style",{},"html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .sG7-3, html code.shiki .sG7-3{--shiki-default:#393A34;--shiki-dark:#393A34}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}",{"title":26,"searchDepth":56,"depth":56,"links":1352},[1353,1354,1355,1356,1357,1358,1364],{"id":15,"depth":56,"text":15},{"id":167,"depth":56,"text":167},{"id":731,"depth":56,"text":732},{"id":991,"depth":56,"text":991},{"id":1117,"depth":56,"text":1117},{"id":1201,"depth":56,"text":1201,"children":1359},[1360,1361,1362,1363],{"id":1205,"depth":80,"text":1206},{"id":1221,"depth":80,"text":1222},{"id":1240,"depth":80,"text":1241},{"id":1260,"depth":80,"text":1261},{"id":1298,"depth":56,"text":1298},null,"大きなフィボナッチ数を効率的に計算するアルゴリズムと実装方法","md",{},"/fibonacci-millionth",false,"2025-12-19T00:00:00.000Z",{"title":5,"description":1366},"2025-12/2025-12-19/fibonacci-millionth",[1375,1376,1377],"algorithm","math","optimization","r0lARF2shvjp7v4hXxsQIxUAev0YeD1IvK77Qu-XU-k",[],[1381,1385,1389,1393,1397],{"title":1382,"path":1383,"publishedAt":1384},"5投稿で10万再生が出なければアカウントを消せ――プラットフォームの「ボーナスリーチ」をハックする","/account-reset-logic","2026-03-19T00:00:00.000Z",{"title":1386,"path":1387,"publishedAt":1388},"(a+b)³ の展開公式を3Dで理解する","/algebraic-identity-a-plus-b-cubed","2026-02-06T00:00:00.000Z",{"title":1390,"path":1391,"publishedAt":1392},"MCPサーバーのオンデマンド化が実装済みだった件","/mcp-ondemand-confirmation","2026-01-07T00:00:00.000Z",{"title":1394,"path":1395,"publishedAt":1396},"Claude Code コンテキスト最適化提案","/claude-code-context-optimization","2025-12-22T00:00:00.000Z",{"title":1398,"path":1399,"publishedAt":1400},"Lighthouseパフォーマンス改善記録","/lighthouse-performance-improvement","2025-12-04T00:00:00.000Z","https://log.eurekapu.com/og/blog/fibonacci-millionth.png?v=2025-12-19T00%3A00%3A00.000Z&title=%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3%83%83%E3%83%81%E6%95%B0%E5%88%97100%E4%B8%87%E7%95%AA%E7%9B%AE%E3%82%92%E6%B1%82%E3%82%81%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AD%E3%83%BC%E3%83%81&author=Kei%20Komatsu&sig=7083f0d2500d3cb3",1785654682625]