<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      卡特蘭數

      卡特蘭數

      默認分類 2009-10-14 23:29:22 閱讀241 評論0字號:


      來源 :http://blog.163.com/lz_666888/blog/static/1147857262009914112922803/

        Catalan數

        中文:卡特蘭數

        原理:

        令h(1)=1,h(0)=1,catalan數滿足遞歸式:

        h(n)= h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1) (其中n>=2)

        另類遞歸式:

        h(n)=((4*n-2)/(n+1))*h(n-1);

        該遞推關系的解為:

        h(n)=C(2n,n)/(n+1) (n=1,2,3,...)

        我并不關心其解是怎么求出來的,我只想知道怎么用catalan數分析問題。

        我總結了一下,最典型的四類應用:(實質上卻都一樣,無非是遞歸等式的應用,就看你能不能分解問題寫出遞歸式了)

        1.括號化問題。

        矩陣鏈乘: P=a1×a2×a3×……×an,依據乘法結合律,不改變其順序,只用括號表示成對的乘積,試問有幾種括號化的方案?(h(n)種)

        2.出棧次序問題。

        一個棧(無窮大)的進棧序列為1,2,3,..n,有多少個不同的出棧序列?

        類似:有2n個人排成一行進入劇場。入場費5元。其中只有n個人有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票,問有多少中方法使得只要有10元的人買票,售票處就有5元的鈔票找零?(將持5元者到達視作將5元入棧,持10元者到達視作使棧中某5元出棧)

        3.將多邊行劃分為三角形問題。

        將一個凸多邊形區域分成三角形區域的方法數?

        類似:一位大城市的律師在她住所以北n個街區和以東n個街區處工作。每天她走2n個街區去上班。如果她

        從不穿越(但可以碰到)從家到辦公室的對角線,那么有多少條可能的道路?

        類似:在圓上選擇2n個點,將這些點成對連接起來使得所得到的n條線段不相交的方法數?

        4.給頂節點組成二叉樹的問題。

        給定N個節點,能構成多少種不同的二叉樹?

        (能構成h(N)個)

      Catalan數的解法

      Catalan數的組合公式為 Cn=C(2n,n) / (n+1);

      此數的遞歸公式為 h(n ) = h(n-1)*(4*n-2) / (n+1)

      /* 大數解

      對于大數來說,就應該使用下面的大數算法。

      使用的公式為:h(n) = h(n-1)*(4*n-2)/(n+1);

      */

      // 0ms

      #include<iostream>

      using namespace std;

      #define MAX 100

      #define BASE 10000

      void multiply(int a[],int Max,int b) //大數乘法,注意參數的傳遞

      {

          int i,array=0;

          for (i = Max-1; i >= 0; i--)   

          {

              array += b * a[i];

              a[i] = array % BASE; // 數組每一位存放大數的四位數字

              array /= BASE;   

          }

      }

      void divide(int a[], int Max, int b) //模擬大數除法

      {

          int i, div = 0;

          for (i = 0; i < Max; i++)   

          {

              div = div * BASE + a[i];

              a[i] = div / b;

              div %= b;

          }

      }

      int main()

      {

          int a[101][MAX],i, n;

          memset(a[1],0,MAX*sizeof(int));

          for (i=2, a[1][MAX-1] = 1; i < 101; i++) // 高坐標存放大數低位

          {

              memcpy(a[i], a[i-1], MAX * sizeof(int));      //h[i] = h[i-1];

              multiply(a[i], MAX, 4 * i - 2);               //h[i] *= (4*i-2);

              divide(a[i], MAX, i + 1);                  //h[i] /= (i+1);

          }

          while (cin >> n)   

          {

              for (i = 0; i < MAX && a[n][i] == 0; i++); //去掉數組前為0的數字。

              cout << a[n][i++];             //輸出第一個非0數

              for (; i < MAX; i++)   

              {

          printf("%04d",a[n][i]);       //輸出后面的數,并每位都保持4位長度!(32767)

         }

              cout << endl;

          }

          return 0;

      }

      AC CODE 2:

      //C(0) = 1 ; (n+2)*C(n+1) = (4n+2)*C(n); 也即是:h(n) = h(n-1) * (4 * n - 2)/(n+1);

      // 0MS

      #include<iostream>

      using namespace std;

      int a[101][101] = {0};

      int main()

      {

          int n,i,j,len,r,temp,t;

          int b[101];

          a[1][0] = 1; // 低坐標存放大數的低位

          len = 1;

          b[1] = 1;

          for (i = 2; i <= 100; i++)

          {

              t = i - 1;

              for (j=0;j<len;j++) // 模擬乘法,從低位開始

         {

          a[i][j] = a[i-1][j] * (4 * t + 2);

         }

              for (r = j = 0; j < len; j++) // 處理相乘結果

              {

                  temp = a[i][j] + r;

                  a[i][j] = temp % 10;

                  r = temp / 10;

              }

              while (r) // 進位處理

              {

                  a[i][len++] = r % 10;

                  r /= 10;

              }

              for (j = len-1, r = 0; j >= 0; j--) // 模擬除法,從高位開始

              {

                  temp = r * 10 + a[i][j];

                  a[i][j] = temp / (t+2);

                  r = temp % (t+2);

              }

              while (!a[i][len-1]) // 高位零處理

         {

          len--;

         }

              b[i] = len; // 記錄結果的長度

          }

          while (cin >> n)

          {  

              for(j = b[n] - 1; j >= 0; j--)

         {

          printf("%d",a[n][j]);

         }

              printf("\n");

          }

          return 0;

      《編程之美》中提到了“買票找零”問題,查閱了下資料,此問題和卡特蘭數 Cn有關,其定義如下:

      卡特蘭數真是一個神奇的數字,很多組合問題的數量都和它有關系,例如:

       

      • Cn= 長度為 2n的 Dyck words的數量。 Dyck words是由 n個 X和 n個 Y組成的字符串,并且從左往右數, Y的數量不超過 X,例如長度為 6的 Dyck words為:

       

      XXXYYY XYXXYY XYXYXY XXYYXY XXYXYY

       

      • Cn= n對括號正確匹配組成的字符串數,例如 3對括號能夠組成:

       

      ((())) ()(()) ()()() (())() (()())

      • Cn= n+1個數相乘,所有的括號方案數。例如, 4個數相乘的括號方案為:

       

       

      ((ab)c)d (a(bc))d (ab)(cd) a((bc)d) a(b(cd))

      • Cn= 擁有 n+1 個葉子節點的二叉樹的數量。例如 4個葉子節點的所有二叉樹形態:

       

       

      • Cn=n*n的方格地圖中,從一個角到另外一個角,不跨越對角線的路徑數,例如, 4×4方格地圖中的路徑有:

       

       

      • Cn= n+2條邊的多邊形,能被分割成三角形的方案數,例如 6邊型的分割方案有:

       

       

      • Cn= 圓桌周圍有 2n個人,他們兩兩握手,但沒有交叉的方案數。

       

      在《Enumerative Combinatorics》一書中,竟然提到了多達 66種組合問題和卡特蘭數有關。

       

      分析

          “卡特蘭數”除了可以使用公式計算,也可以采用“分級排列法”來求解。以 n對括弧的合法匹配為例,對于一個序列 (()而言,有兩個左括弧,和一個右括弧,可以看成“抵消了一對括弧,還剩下一個左括弧等待抵消”,那么說明還可以在末尾增加一個右括弧,或者一個左括弧,沒有左括弧剩余的時候,不能添加右括弧。

          由此,問題可以理解為,總共 2n個括弧,求 1~2n級的情況,第 i 級保存所有剩余 i 個左括號的排列方案數。 1~8級的計算過程如下表:

          計算過程解釋如下: 1級:只能放 1個“(”; 2級:可以在一級末尾增加一個“)”或者一個“ (”

      以后每級計算時,如果遇到剩余 n>0個“(”的方案,可以在末尾增加一個“ (”或者“ )”進入下一級;遇到剩余 n=0個“(”的方案,可以在末尾增加一個“ (”進入下一級。

       

      奇數級只能包含剩余奇數個“(”的排列方案

      偶數級只能包含剩余偶數個“(”的排列方案

       

      從表中可以看出,灰色部分可以不用計算。

      解法

      關鍵代碼為:

      double Catalan(int n) { if (n == 0) return 1; for (int i = 2; i <= 2 * n; i++) { var m = i <= n ? i : 2 * n + 1 - i; for (int j = (i - 1) & 1; j <= m; j += 2) { if (j > 0) arr[j - 1] += arr[j]; if (j < n) arr[j + 1] += arr[j]; arr[j] = 0; } } return arr[0]; }

       

      其中:

      n為 Cn中的 n;

      arr = new double[n + 1];//arr[i]代表有 k個括弧的時候,剩余 "("個數為 i的排列方案個數 arr[1] = 1;

       

      討論

      算法復雜度為  O(n^2),空間復雜度為 O(n+1)。相對于利用公式計算而言,此方法的優勢在于——沒有乘除法,只有加法。

      posted on 2010-03-28 17:39  大寶pku  閱讀(988)  評論(1)    收藏  舉報

      導航

      主站蜘蛛池模板: 亚洲国产亚洲综合在线尤物| 国产亚洲精品在av| 不卡乱辈伦在线看中文字幕| 亚洲鸥美日韩精品久久| 国产成人高清亚洲综合| 中文字幕免费不卡二区| 亚洲欧洲成人a∨在线| 国内精品免费久久久久电影院97| 一本一本久久aa综合精品| 国产jizzjizz视频| 狠狠色狠狠综合久久| 国产在线一区二区不卡| 国产成人综合在线女婷五月99播放| 国产卡一卡二卡三免费入口| 国产亚洲真人做受在线观看| 精品无码一区二区三区的天堂| 2020国产成人精品视频| 欧美人与禽2o2o性论交| 99精品国产一区二区三区2021| 岛国最新亚洲伦理成人| 精品国际久久久久999波多野| 人妻日韩精品中文字幕| 国产日韩av一区二区在线| аⅴ天堂国产最新版在线中文| 石原莉奈日韩一区二区三区| 亚洲精品国产一区二区在线观看| 久久精品国产一区二区蜜芽| 亚洲综合久久一区二区三区| 91孕妇精品一区二区三区| 成人激情视频一区二区三区| 中文字幕日韩精品有码| 免费人成年激情视频在线观看| 国产乱沈阳女人高潮乱叫老| 国产91精品调教在线播放| 日韩亚洲视频一区二区三区| 宅男噜噜噜66在线观看| 亚洲欧美综合人成在线| 国偷自产一区二区三区在线视频| 国产精品成人av电影不卡| 精品久久人人做爽综合| 欧美肥老太牲交大战|