publicclassFib{publicstaticlongfib(intn){long a =1L, b =1L, c =1L;for(int i =1; i < n; i++){
c = b;
b = a + b;
a = c;}return c;}publicstaticvoidmain(Stringargs[]){System.out.println(fib(100));// 3736710778780434371
}}
deffib(n: Int) ={var(a, b, c)=(BigInt(1),BigInt(1),BigInt(1))vari=1while(i < n){
c = b
b = a + b
a = c
i += 1}
c
}@maindefmain():Unit= println(fib(100)) // 354224848179261915075
Java:
importjava.math.BigInteger;publicclassFibJava{publicstaticBigIntegerfib(intn){BigInteger a =BigInteger.valueOf(1L), b =BigInteger.valueOf(1L), c =BigInteger.valueOf(1L);for(int i =1; i < n; i++){
c = b;
b = a.add(b);
a = c;}return c;}publicstaticvoidmain(Stringargs[]){System.out.println(fib(100));// 354224848179261915075
}}
@scala.annotation.tailrecdeffibRec(x: BigInt,y: BigInt,i: Int):BigInt=if(i == 0) x else fibRec(y, x + y, i - 1)
deffib(n: Int):BigInt= fibRec(0,1, n)
@maindefprintFib100():Unit= println(fib(100)) // 354224848179261915075
Java:
importjava.math.BigInteger;publicclassFibJava{privatestaticBigInteger_fib(BigIntegerx,BigIntegery,inti){return(i ==0)? x :_fib(y, x.add(y), i -1);}publicstaticBigIntegerfib(intn){return_fib(BigInteger.valueOf(0L),BigInteger.valueOf(1L), n);}publicstaticvoidmain(Stringargs[]){System.out.println(fib(100));// 354224848179261915075
}}
#include<iostream>intfib(intn){int a =0, b =1, c =0;for(int i =0; i < n ; i++){
c = b;
b =(a + b)%1000000007;
a = c;}return a;}intmain(){
std::cout <<fib(1000000000)<<"\n";return0;}
~ $ g++ -O2 fibonacci.cc -o fibonacci-cpp~ $ time ./fibonacci-cpp21./fibonacci-cpp 2.47s user 0.00s system 99% cpu 2.473 total
C++ 启用 gcc-O2 编译优化,运行耗时 2.47s .
Rust 尾递归:
fnmain(){fnfib_m(n:i32)->i32{fn_fib(x:i32, y:i32, i:i32, n:i32)->i32{if i == n { x }else{_fib(y,(x+y)%1000000007, i+1, n)}}_fib(0,1,0, n)}println!("fibM(10^9) = {}",fib_m(1_000_000_000));}
~ $ time ./fibonacci_rsfibM(10^9)=21./fibonacci_rs 2.53s user 0.00s system 99% cpu 2.500 total
~ $ time python2.7 fibonacci-loop.py21python2.7 fibonacci-loop.py 57.04s user 0.01s system 99% cpu 57.103 total~ $ time python fibonacci-loop.py21python3.7 fibonacci-loop.py 108.94s user 0.02s system 99% cpu 1:49.00 total~ $ time python3.8 fibonacci-loop.py21python3.8 fibonacci-loop.py 112.31s user 0.01s system 99% cpu 1:52.33 total~ $ time python3.9 fibonacci-loop.py21python3.9 fibonacci-loop.py 120.74s user 0.01s system 99% cpu 2:00.81 total~ $ time pypy fibonacci-loop.py21pypy fibonacci-loop.py 3.11s user 0.01s system 99% cpu 3.134 total~ $ time pypy3 fibonacci-loop.py21pypy3 fibonacci-loop.py 3.13s user 0.01s system 99% cpu 3.150 total
~ $ time python2.7 fibonacci-loop.py21python2.7 fibonacci-loop.py 53.61s user 0.01s system 99% cpu 53.764 total~ $ time python3.9 fibonacci-loop.py21python3.9 fibonacci-loop.py 84.24s user 0.01s system 99% cpu 1:24.49 total~ $ time python3.10 fibonacci-loop.py21python3.10 fibonacci-loop.py 82.86s user 0.01s system 99% cpu 1:23.10 total~ $ time python3.11 fibonacci-loop.py21python3.11 fibonacci-loop.py 73.94s user 0.00s system 99% cpu 1:14.14 total~ $ time python3.12 fibonacci-loop.py21python3.12 fibonacci-loop.py 81.61s user 0.01s system 99% cpu 1:21.83 total$ time python3.13 fibonacci-loop.py21python3.13 fibonacci-loop.py 82.50s user 0.00s system 99% cpu 1:22.76 total
scala> testFastPowMatrix(1_000_000_000L)
fibM(1000000000) =21, time cost: 0.034571 ms
emmmmmm,只需要 0.035ms. 继续加大剂量:
scala> testFastPowMatrix(1_000_000_000L)
fibM(1000000000) =21, time cost: 0.034571 ms
scala> testFastPowMatrix(10_000_000_000L)
fibM(10000000000) =815449418, time cost: 0.03718 ms
scala> testFastPowMatrix(100_000_000_000L)
fibM(100000000000) =224788301, time cost: 0.039211 ms
scala> testFastPowMatrix(1_000_000_000_000L)
fibM(1000000000000) =730695249, time cost: 0.038571 ms
scala> testFastPowMatrix(1000_000_000_000_000L)
fibM(1000000000000000) =648325137, time cost: 0.0467 ms
scala> testFastPowMatrix(1_000_000_000_000_000_000L)
fibM(1000000000000000000) =209783453, time cost: 0.054571 ms
scala> testFastPowMatrix(Long.MaxValue)
fibM(9223372036854775807) =884968410, time cost: 0.064401 ms
可见我们一直加大 n 到 Long.MaxValue = 9223372036854775807 也即 263−1, 仍然只花费了不到 0.07ms.
这其实很好理解,因为我们的快速幂算法时间复杂度为 O(log2n) .
由此我们可以猜测,其实这个算法对第3小题求 f(101000)=F101000mod(109+7) 也是胜任的,只是这个 101000 远超我们实现中的 Long 数值范畴,需要考虑能处理 n 为 BigInt 的实现。
可以考虑一个基于数值泛型的实现,因为不管输入 n 为什么类型,只需要取得 n 的二进制表示即可。考虑以下 type class:
given BinaryNumeric[Long] with{defhalf(x: Long):Long= x >> 1defisZero(x: Long):Boolean= x == 0LdefisOdd(x: Long):Boolean=(x & 1L) == 1L}
scala> testFastPowMatrix(10,9)
time cost: 48.3245 ms, result =21, p =10, q =9
scala> testFastPowMatrix(10,9)
time cost: 0.186812 ms, result =21, p =10, q =9
scala> testFastPowMatrix(10,9)
time cost: 0.191382 ms, result =21, p =10, q =9
scala> testFastPowMatrix(10,1000)
time cost: 1.510469 ms, result =552179166, p =10, q =1000
scala> testFastPowMatrix(10,1000)
time cost: 0.612577 ms, result =552179166, p =10, q =1000
scala> testFastPowMatrix(10,1000)
time cost: 0.539977 ms, result =552179166, p =10, q =1000
scala> testFastPowMatrix(10,9)
time cost: 0.141252 ms, result =21, p =10, q =9
scala> testFastPowMatrix(10,1000)
time cost: 0.687648 ms, result =552179166, p =10, q =1000
scala> testFastPowMatrix(10,10000)
time cost: 3.667316 ms, result =508797063, p =10, q =10000
scala> testFastPowMatrix(10, 100_000)
time cost: 16.345542 ms, result =322994487, p =10, q =100000
scala> testFastPowMatrix(10, 1_000_000)
time cost: 168.761524 ms, result =305562778, p =10, q =1000000
scala> testFastPowMatrix(10, 10_000_000)
time cost: 730.109804 ms, result =63990505, p =10, q =10000000
scala> testFastPowMatrix(10, 100_000_000)
time cost: 4525.576374 ms, result =761244216, p =10, q =100000000
scala> testFastPowMatrix(List.fill(1000)(BigInt(10)).product, 100_000)
time cost: 3268.0884 ms, result =761244216, p =10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, q =100000
使用这个小技巧,成功地把计算 f(10108) 的耗时从 4.5s 缩减到 3.3s.
注意到特征矩阵 Matrix 中, a12 总是和 a21 相等,可以从 case class 中去掉 a21, 进一步优化计算代价。重构如下:
scala> testFastPowMatrixOpt(List.fill(1000)(BigInt(10)).product, 100_000)
time cost: 2788.598254 ms, result =761244216
scala> testFastPowMatrixOpt(List.fill(1000)(BigInt(10)).product, 100_000)
time cost: 2785.836456 ms, result =761244216
scala> testFastPowMatrixOpt(List.fill(1000)(BigInt(10)).product, 100_000)
time cost: 2828.199939 ms, result =761244216
scala> (0 to 100).map(x=> x -> Fa(x)).foreach(println)
(0,1)(1,1)(2,1)(3,3)(4,5)(5,9)(6,17)(7,31)(8,57)(9,105)(10,193)(11,355)(12,653)(13,1201)(14,2209)(15,4063)(16,7473)(17,13745)(18,25281)(19,46499)(20,85525)(21,157305)(22,289329)(23,532159)(24,978793)(25,1800281)(26,3311233)(27,6090307)(28,11201821)(29,20603361)(30,37895489)(31,69700671)(32,128199521)(33,235795681)(34,433695873)(35,797691075)(36,1467182629)(37,2698569577)(38,4963443281)(39,9129195487)(40,16791208345)(41,30883847113)(42,56804250945)(43,104479306403)(44,192167404461)(45,353450961809)(46,650097672673)(47,1195716038943)(48,2199264673425)(49,4045078385041)(50,7440059097409)(51,13684402155875)(52,25169539638325)(53,46294000891609)(54,85147942685809)(55,156611483215743)(56,288053426793161)(57,529812852694713)(58,974477762703617)(59,1792344042191491)(60,3296634657589821)(61,6063456462484929)(62,11152435162266241)(63,20512526282340991)(64,37728417907092161)(65,69393379351699393)(66,127634323541132545)(67,234756120799924099)(68,431783823692756037)(69,794174268033812681)(70,1460714212526492817)(71,2686672304253061535)(72,4941560784813367033)(73,9088947301592921385)(74,16717180390659349953)(75,30747688477065638371)(76,56553816169317909709)(77,104018685037042898033)(78,191320189683426446113)(79,351892690889787253855)(80,647231565610256598001)(81,1190444446183470297969)(82,2189568702683514149825)(83,4027244714477241045795)(84,7407257863344225493589)(85,13624071280504980689209)(86,25058573858326447228593)(87,46089903002175653411391)(88,84772548141007081329193)(89,155921025001509181969177)(90,286783476144691916709761)(91,527477049287208180008131)(92,970181550433409278687069)(93,1784442075865309375404961)(94,3282100675585926834100161)(95,6036724301884645488192191)(96,11103267053335881697697313)(97,20422092030806454019989665)(98,37562083386026981205879169)(99,69087442470169316923566147)(100,127071617887002752149434981)
scala> (0 to 50).map(x=> x -> Fb(x)).foreach(println)
(0,1)(1,1)(2,1)(3,1)(4,43)(5,841)(6,16717)(7,332137)(8,6599083)(9,131114173)(10,2605047817)(11,51758509153)(12,1028366255827)(13,20432140983745)(14,405956907681613)(15,8065772990971753)(16,160255171696481107)(17,3184037051900036389)(18,63262182683711092201)(19,1256927508277275719473)(20,24973320458494220381563)(21,496183535339626230014521)(22,9858444781154053917544237)(23,195872951400009695996934121)(24,3891710502197418260130836059)(25,77322624306527561296481515405)(26,1536288022007942131643192764777)(27,30523807329775656153953496341185)(28,606463632182409515806053376732867)(29,12049549821430619720713032522579313)(30,239407019966975630627283579200701165)(31,4756669092112429116061847731573517161)(32,94508092765946256843474105015675108163)(33,1877738271318367914391637250695625511285)(34,37307926891570572836621731354299630541321)(35,741254215354267094582920223214060136552081)(36,14727642556429898267383698808553745791464747)(37,292616825344191097288211813088433081762944745)(38,5813870491929493595640135173004421131894693901)(39,115513146098724484996588253444076560745199672681)(40,2295078113650400421344034939841589086301401230475)(41,45599862229146260100651441265030693144218017173597)(42,906002903757313230487400199550456575853255934967625)(43,18000959246144887252048391644170292823216566461833761)(44,357652864508000214808551189907798162074513806557620019)(45,7106041947079712023319933570079342401675998670155139617)(46,141186712493188771157545324818560026764378498788606297101)(47,2805174516711974047238346894976816660747702456541868786025)(48,55734735445376130567753078296705249317533310174665704923315)(49,1107368085892610142870194751343238579084469079571143504670149)(50,22001792380539533181964009431690043444360246054101330128953513)