青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

雁過無痕

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::

pdf版本下載

㈠ Fibonacci

剛接觸Fibonacci數的時候,在網上看到“矩陣法”,看到要先實現一個矩陣乘法,感覺太麻煩了。后來仔細觀察Fibonacci數列,發現有下面的規律:

F(n)     = F(k)*F(n+1-k) + F(k-1)*F(n-k)          =>

F(2*n)   = F(n+1) * F(n) + F(n) * F(n - 1)

F(2*n+1) = F(n+1) * F(n+1) + F(n) * F(n)

根據該公式:要計算F(n),只需先計算出F(n/2)和F(n/2+1),于是得出一個數的O(log n)解法。(例如:計算F(13) => 計算F(6)、F(7) => 計算F(3)、F(4) => 計算F(1)、F(2)。)

再后來無意間發現,“矩陣法”根本就不必實現一個矩陣,網上廣為流傳的糟糕的做法,掩蓋了“矩陣法”的優美。

 

     先回顧下Fibonacci數列的矩陣法:

  

上式中,對系數矩陣A求n次方,有O(log n)解法,因而整個算法是O(log n)。

某些介紹矩陣法的文章,會“偷懶”采用上面的第二種寫法,而不是第一種寫法。偷懶的結果,總是要付出代價的。對上面矩陣法的實現,存在兩個盲點,也正由于這兩個盲點,使“矩陣法”的實現代碼看起來很復雜,失去了簡潔之美。

 

盲點之一:對系數矩陣A求n次方,可以不采用矩陣乘法來實現。

將F(1) = F(2) = 1, F(0) = 0代入上面的公式1,得到:


    上式,對任意 n >=1都成立,也就是說A的任意n次方,只要用兩個變量表示,根本沒必要去實現矩陣乘法。

另外,由 A^n = A^k * A^(n-k),結合上式,很容易就得到前面提到的公式:

F(n) = F(k)*F(n+1-k) + F(k-1)*F(n-k)

 

 

盲點之二: A的n次方計算方法。

計算一個數m的n次方,

若采用迭代法的話,一般是將m^n,拆分成m、m^2、m^4、m^8…中的幾個的乘積。

若采用遞歸的話,則是將m^n拆分成計算m^(n/2)

 

//迭代法:

int pow1(int m, unsigned n)

{

   int result = 1;

  int factor = m;

   while (n) {

     if (n & 1) { result *= factor; }

     factor *= factor;

     n /= 2u;

   }

   return result;

}

 

//遞歸法

int pow2(int m, unsigned n)

{

 if (n == 0) return 1;

 int square_root = pow2(m, n / 2);

 int result = square_root * square_root;

 if (n & 1) result *= m;

 return result;

}

 

對于計算一個整數的n次方,顯然第一種解法效率高,但對計算矩陣的n次方,第二種解法(遞歸法)則更簡單。該遞歸算法也可寫成迭代形式:

 

int pow3(int m, unsigned n)

{

 if (n == 0) return 1;

 unsigned flag = n;               //小等于n的最大的2的k次冪

 for (unsigned value = n; value &= (value - 1); ) flag = value;

 

 int result = m;

 while (flag >>= 1) {

    result *= result;

    if (n & flag) result *= m;

 }

 return result;

}

 

(求小等于n的最大的2k次冪(或求二進制表示中的最高/左位1),有兩種不通用O(1)方法:一種是使用位掃描匯編指令、另外一種是利用浮點數的二進制表示。)

unsigned extract_leftmost_one(unsigned num)

{

 union {

    unsigned i;

    float f;

 } u;

 u.f = (float)num;

 return u.i >> 23;

}

 

最后可得到如下代碼:

采用一般迭代法計算A^n

typedef unsigned uint;

 

static inline void matrix_multiply(uint& b1, uint& b2, uint a1, uint a2)

{

 const uint r1 =   a1 * b1 + a1 * b2 + a2 * b1;

 const uint r2 =   a1 * b1 + a2 * b2;

 b1 = r1;

 b2 = r2; 

}

 

uint fib_matrix(uint num)

{

 uint b1 = 0, b2 = 1;

 uint a1 = 1, a2 = 0;

 for (; num != 0; num >>= 1) {

    if (num & 1) matrix_multiply(b1, b2, a1, a2);

    matrix_multiply(a1, a2, a1, a2);

 }

 return b1;

}

 

 

采用新的迭代法計算A^n

typedef unsigned uint;

uint fibonacci(uint num)

{

 if (num == 0) return 0;

 uint flag = num;             //extract_leftmost_one

 for (uint value = num; value &= value - 1; ) flag = value;

 

 uint a1 = 1, a2 = 0;

 while (flag >>= 1) {

   const uint r1 = a1 * a1 + 2 * a1 * a2;

    const uint r2 = a1 * a1 +     a2 * a2; 

    a1 = r1;

    a2 = r2;

    if (num & flag) {

      a1 = r1 + r2;

      a2 = r1;

    }

 }

 return a1;

}

 

 

上面提到的方法,很容易擴展到三階矩陣,下面是《編程之美》書上的一道擴展題的解法:

(具體分析見下一節)

 

假設:A(0)=1, A(1)=2, A(2)=2,對n>2都有A(n)=A(n-1)+A(n-2)+A(n-3),

1. 對于任何一個給定的n,如何計算出A(n)?

2. 對于n非常大的情況,如n=2^60的時候,如何計算A(n) mod M (M < 100000)呢?

 

typedef unsigned uint;

typedef unsigned long long uint64;

 

uint fib_ex(uint64 num, uint M)

{

 assert(M != 0);

 const uint g0 = 1, g1 = 2, g2 = 2;

 if (num == 0) return g0;

 uint64 flag = num;

 for (uint64 value = num; value &= value - 1; ) flag = value;

 

 uint64 a1 = 0, a2 = 1, a3 = 0;

 while (flag >>= 1) {

    const uint64 r1 = 2 * (a1 + a2 + a3) * a1 +      a2 * a2;

    const uint64 r2 = 2 * (a1 + a2)      * a1 + 2 * a2 * a3; 

    const uint64 r3 =     (a1 + 2 * a2) * a1 +      a3 * a3;

    a1 = r1;

    a2 = r2;

    a3 = r3;

    if (num & flag) {

      a1 = r1 + r2;

      a2 = r1 + r3;

      a3 = r1;

    }

    a1 %= M;

    a2 %= M;

    a3 %= M;

 }

 return (a1 * g2 + a2 * g1 + a3 * g0) % M;

}

 

 

㈡ 擴展數列的通解:

    下面將前面的結果擴展到任意m階數列:



例子:

 

   m=2 g(n) = f1 * g(n-1) + f2 * g(n-2) 初始值為:g0 = g(0) g1=g(1)

     設系數矩陣為AAn的最后一行為(a1 a2),則

倒數第二行為:(f1*a1 + a2 f2*a1)

即:

     系數矩陣A              An

      f1 f2        f1*a1 + a2    f2*a1

      1   0            a1         a2

 

 

typedef unsigned uint;

 

uint fib_matrix2(uint num)

{

 if (num == 0) return g0;

 uint flag = num;

 for (uint value = num; value &= value - 1; ) flag = value;

 /*

     A               A^n

    f1 f2   f1*a1 + a2    f2*a1

    1   0       a1         a2

 */

 uint a1 = 1, a2 = 0; // 0 0 ... 1 0

 while (flag >>= 1) {

    const uint r1 = f1 * a1 * a1 + 2 * a1 * a2;

    const uint r2 = f2 * a1 * a1 +      a2 * a2; 

    a1 = r1;

    a2 = r2;

    if (num & flag) {

      a1 = f1 * r1 + r2;

      a2 = f2 * r1;

    }

 }

 return a1 * g1 + a2 * g0;

}

 

② m=3 g(n) = f1 * g(n-1) + f2 * g(n-2) + f3*g(n-3),初始值為:g0 = g(0)g1=g(1), g2=g(2)

設系數矩陣為AAn的最后一行為(a1 a2 a3),則

倒數第二行為:(f1*a1 + a2 f2*a1 + a3 f3*a1)

    倒數第三行為:((f1*f1+f2)*a1 + f1*a2 + a3   (f1*f2+f3)*a1 + f2*a2  f1*f3*a1 + f3*a2)

即:

    系數矩陣A                                 An 

    f1 f2 f3    (f1*f1+f2)*a1 + f1*a2 + a3 (f1*f2+f3)*a1 + f2*a2   f1*f3*a1 + f3*a2

    1   0   0             f1*a1 + a2                 f2*a1 + a3         f3*a1

    0   1   0               a1                      a2                 a3

 

typedef unsigned uint;

 

uint fib_matrix3(uint num)

{

 if (num == 0) return g0;

 uint flag = num;

 for (uint value = num; value &= value - 1; ) flag = value;

 /*

       A                                       A^n

    f1 f2 f3   (f1*f1+f2)*a1 + f1*a2 + a3 (f1*f2+f3)*a1 + f2*a2   f1*f3*a1 + f3*a2

    1   0   0            f1*a1 + a2                  f2*a1 + a3         f3*a1

    0   1   0               a1                          a2                 a3

 */

 uint a1 = 0, a2 = 1, a3 = 0; // 0 0 ... 1 0

 while (flag >>= 1) {

    const uint r1 = (f1 * f1 + f2) * a1 * a1 +  2 * f1 * a1 * a2 + 2 * a1 * a3 + a2 * a2;

    const uint r2 = (f1 * f2 + f3) * a1 * a1 + 2 * f2 * a1 * a2 + 2 * a2 * a3; 

    const uint r3 = (f1 * f3)      * a1 * a1 + 2 * f3 * a1 * a2 +     a3 * a3;

    a1 = r1;

    a2 = r2;

    a3 = r3;

    if (num & flag) {

      a1 = f1 * r1 + r2;

      a2 = f2 * r1 + r3;

      a3 = f3 * r1;

    }

 }

 return a1 * g2 + a2 * g1 + a3 * g0;

}

 

 

posted on 2012-02-28 22:14 flyinghearts 閱讀(2445) 評論(11)  編輯 收藏 引用 所屬分類: 算法

評論

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-02-28 23:07 四季青租房
不錯,學習了  回復  更多評論
  

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-02-29 09:11 tb
很不錯啊  回復  更多評論
  

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-03-20 01:51 wywcgs
1. 矩陣乘法可以輕易擴展到求前n項和。
2. 后面那個A^n = \sum_{i=0}^{n-1}f_i*A^i的公式不是你那么用的。按你這么用你到底要推多少的東西。事實上你把那個系數當成多項式A^i的系數,分治之后再square就行了。而且你要是愿意折騰的話還能用fft優化  回復  更多評論
  

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-03-20 20:58 flyinghearts
@wywcgs

那個A^n = sum(...) 公式根本沒用到。只是在推導過程中,發現有這個性質,就寫上了。

你覺得你那樣做更高效的話,麻煩你把三階的情況實現下,沒代碼沒真相。




  回復  更多評論
  

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-03-21 13:55 wywcgs
@flyinghearts

不如您實現一下1000階的吧,三階太小兒科了。f(n) = f(n-1) + f(n-2) + .... + f(n-1000),f(0) = f(1) = .... = f(999) = 1。
代碼我早在很久以前就實現過無數份了,我現在隨手就能拿出一份,n等于多少都行。不知您的代碼要寫多久  回復  更多評論
  

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-03-21 20:17 flyinghearts
@wywcgs

你要么根本就沒看我的算法、要么就是沒看懂。 不要說1000階,就是10000階、任意階,都不成問題。三階那種寫法,是對三階的情況進行具體優化。

既然你可以隨手拿出一份,那就把代碼貼出來吧。



  回復  更多評論
  

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-03-22 23:29 wywcgs
@flyinghearts

沒說你的不行。只是說你要推的東西略多。實現復雜。

貼代碼?懶得貼。你給個郵箱,我傳你份。  回復  更多評論
  

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-03-24 21:19 flyinghearts
@wywcgs
qq郵箱。這個用戶名。

  回復  更多評論
  

# re: Fibonacci數計算中的兩個思維盲點及其擴展數列的通用高效解法 2012-04-04 21:03 flyinghearts
@wywcgs
代碼呢??  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品一二三| 亚洲午夜一区二区| 亚洲精品美女在线| 激情文学一区| 亚洲国产老妈| 亚洲美女网站| 亚洲天堂av综合网| 久久精品在线免费观看| 欧美在线一区二区三区| 久久午夜av| 亚洲福利视频专区| 亚洲国产mv| 日韩午夜三级在线| 久久成人18免费网站| 蜜桃av一区二区在线观看| 麻豆视频一区二区| 国产精品成人免费精品自在线观看| 国产精品国产三级国产a| 国产欧美精品久久| 亚洲精品小视频在线观看| 欧美激情一区二区在线| 欧美日韩精品在线播放| 国产亚洲欧美另类中文| 亚洲狼人综合| 久久精品国产亚洲一区二区| 欧美激情中文字幕一区二区| 一区二区高清在线观看| 久久久噜噜噜久噜久久| 国产精品v欧美精品∨日韩| 激情综合自拍| 欧美一级视频精品观看| 亚洲区欧美区| 久久久久国产精品午夜一区| 欧美日韩国产成人在线观看| 国产欧美精品一区二区三区介绍 | 欧美日韩和欧美的一区二区| 国产伦精品一区二区三区视频黑人| 一区在线免费| 性久久久久久久久| 最近看过的日韩成人| 国产一区二区三区黄| 亚洲高清在线精品| 欧美女同视频| 国产精品一区二区在线| 最新国产精品拍自在线播放| 欧美一区二区三区四区视频| 亚洲黄色视屏| 久久久欧美精品| 亚洲精品1区2区| 日韩视频一区二区三区在线播放| 欧美亚洲一级| 一区二区三区色| 欧美激情综合| 亚洲麻豆av| 欧美电影免费观看网站| 久久精品国产91精品亚洲| 欧美性jizz18性欧美| 一本色道久久加勒比88综合| 亚洲国产欧美一区二区三区丁香婷| 香蕉成人伊视频在线观看 | 日韩一二三在线视频播| 嫩模写真一区二区三区三州| 欧美一区国产一区| 国内一区二区在线视频观看| 久久久久国产一区二区三区| 久久99在线观看| 狠久久av成人天堂| 免费观看成人网| 麻豆精品视频在线观看| 亚洲激情在线| 99国产精品私拍| 国产精品免费看久久久香蕉| 欧美亚洲色图校园春色| 亚洲永久精品大片| 国产日韩欧美一区二区| 免费日韩av| 欧美人体xx| 欧美在线日韩| 久久亚洲精品网站| 亚洲精品精选| 亚洲精选一区| 国产伦精品一区二区| 久久久久久黄| 蜜臀av国产精品久久久久| 亚洲另类在线视频| 在线亚洲电影| 伊人久久久大香线蕉综合直播| 蜜臀久久99精品久久久久久9 | 久久综合综合久久综合| 亚洲精品国产品国语在线app| 亚洲久久一区| 狠狠综合久久| 亚洲免费成人av| 国产亚洲在线| 亚洲精品自在在线观看| 国产一区二区三区精品久久久| 欧美美女视频| 亚洲电影在线免费观看| 亚洲美女尤物影院| 国模私拍一区二区三区| 亚洲日本在线观看| 国产一区二区丝袜高跟鞋图片| 亚洲日本va在线观看| 国产在线日韩| 亚洲一区精品视频| 日韩亚洲视频在线| 老司机一区二区三区| 性伦欧美刺激片在线观看| 欧美gay视频激情| 久久精品一区蜜桃臀影院| 欧美日韩日日夜夜| 亚洲国产欧洲综合997久久| 国产一区二区高清| 亚洲欧美成人一区二区三区| 99成人精品| 欧美激情久久久| 欧美成人a∨高清免费观看| 国产亚洲福利社区一区| 亚洲一区二区三区影院| 99综合电影在线视频| 久久手机免费观看| 久久精品久久99精品久久| 欧美性猛片xxxx免费看久爱| 亚洲国产综合视频在线观看| 国产拍揄自揄精品视频麻豆| 亚洲高清色综合| 在线观看成人小视频| 免费亚洲电影| 国产精品成人久久久久| 欧美成人r级一区二区三区| 欧美一区激情视频在线观看| 亚洲图片在区色| 久久久视频精品| 午夜精品久久久久久久久久久| 美女诱惑一区| 一区二区三区欧美成人| 欧美日韩激情小视频| 欧美sm极限捆绑bd| 国内精品免费午夜毛片| 亚洲午夜精品17c| 国内偷自视频区视频综合| 午夜精品在线看| 在线一区二区三区做爰视频网站| 看片网站欧美日韩| 久久天堂成人| 国产精品国内视频| 99国内精品| 一本色道久久综合| 欧美成人中文字幕在线| 亚洲精品精选| 一本一道久久综合狠狠老精东影业 | 香蕉久久一区二区不卡无毒影院 | 韩国福利一区| 亚洲男人第一av网站| 亚洲精品乱码久久久久久久久| 欧美一级免费视频| 欧美亚洲三级| 国产精品一区二区你懂的| 99精品福利视频| 韩国av一区二区三区四区| 蜜月aⅴ免费一区二区三区| 欧美va天堂| 最近看过的日韩成人| 美女精品一区| 午夜精品视频网站| 亚洲第一主播视频| 麻豆91精品91久久久的内涵| 免费91麻豆精品国产自产在线观看 | 欧美激情视频一区二区三区不卡| 亚洲国产精品黑人久久久| 欧美韩国日本综合| 欧美成人一区二区在线| 精品成人在线| 麻豆9191精品国产| 99精品欧美一区二区三区| 亚洲一区二区在线播放| 国内精品久久久久久影视8| 久久久久久久欧美精品| 欧美黑人在线观看| 一区二区三区国产精华| 国产精品人人做人人爽人人添| 久久夜色精品国产噜噜av| 亚洲国产精品999| 亚洲国内自拍| 欧美日韩综合精品| 欧美成人免费在线视频| 99国产精品久久久久久久久久| 亚洲永久免费观看| 激情综合色综合久久| 久久天堂精品| 一区二区三区成人| 国产精品自拍在线| 欧美日韩中文字幕在线视频| 一区二区欧美精品| 老司机免费视频久久| 一区二区三区你懂的| 国产精品视频免费在线观看| 久久精品中文字幕一区| 日韩亚洲欧美成人| 欧美成人精品一区二区三区|