1. 程式人生 > >斐波那契 [ Fibonacci] 數列之大整數求和

斐波那契 [ Fibonacci] 數列之大整數求和

cst 狀態 完美數 cstring 進行 class n-1 != 美的

之前做到一題, 不過由於Honor Code的緣故就不說是啥了, 很多人都知道 (-_-)

大概是說有n個牌,每個牌只有A,B兩種狀態. 當出現連續3個牌的狀態一樣時,認為不完美.

給出一個[1, 10000]的整數, 讓求出完美的排列個數

那麽我們就可以分析一下:

/*-------------------------------------------------------------------------------
分析:
首先要求出不美觀的個數,但是嘗試可以發現美觀的排列更容易分析
而總的排列個數為 2^n 故而求出n個骨牌美觀的排列數,設為F(n)
進而讓 2^n - F(n) 的結果就是所求.


那麽我們探索F(n)的方程
假設已經有骨牌排列 [][n-1][n-2][n-3]...
前 n-1 塊排列已經是美觀的,那麽分析第 n 塊骨牌的情況
若 [n-1][n-2] 的顏色一樣,需美觀那麽 第n塊的顏色被註定
而[n-1][n-2]的顏色一樣,必然[n-3]的顏色和這2塊不一樣
這就說明,第[n-3]塊,或者說前 n-3 塊牌的排列決定了第n塊的排列

若[n-1][n-2]的顏色不一樣,已知前 n-1已經是美觀的排列
那麽F(n-1) = [n-1][n-2] 顏色一樣 + 顏色不一樣2種情況

那麽第n-1, n-2塊牌不一樣的 個數 就等於 F(n-1) - F(n-3)

    由於第n-1, n-2塊牌子顏色不同,故而第 n塊牌是有2種方法的
綜上所述,F(n) = F(n-1) + F(n-1) - F(n-3) = 2F(n-1) - F(n-3)
有斐波那契數列 U(n) = U(n-1) + U(n-2)
又有 U(n-1) = U(n-2) + U(n-3) 故而 U(n-2) = U(n-1) - U(n-3)
代入原式就有 U(n) = 2U(n-1) - U(n-3) 和F(n) 同
故而F(n)和斐波那契數列遞推式等同


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

那麽, 最終的結果就是 2^n - F(n) 了! // 需完成1次大整數加法和1次大整數減法

我代碼裏的減法是閹割版本的..因為2^n - F(n)必然 > 0, 所以沒考慮負數的問題.

在這裏是足夠用了...
-------------------------------------------------------------------------------*/

技術分享
  1 // 假設美觀個數為F(n),F(n) = F(n-1)+F(n-2)
  2 // F(1) = 2,  F(2) = 4,  F(3) = 6
  3 #include<iostream>
  4 #include<cstring>
  5 using namespace std;
  6 // Function Add(char* addA,char* addB,char* Result)
  7 // Result = addA + addB ,返回 Result
  8 void Add(char* addA,char* addB,char* Result){
  9     int curIndexA,curIndexB,carry;          // 2個加數計算的當前下標,進位
 10     int tempSum,resultIndex,longerLength;   
 11     int valueA,valueB;
 12 
 13     char *tempResult = new char[5000];
 14     
 15     int lengthA = strlen(addA);
 16     int lengthB = strlen(addB);
 17     longerLength = lengthA > lengthB ? lengthA+2 : lengthB+2;
 18         tempResult = new char[longerLength * sizeof(char)];
 19 
 20     curIndexA = lengthA - 1;                // 從個位數開始計算 即 length-1
 21     curIndexB = lengthB - 1;
 22 
 23     carry = 0;
 24     resultIndex = 0;
 25     tempSum = 0;
 26 
 27     while (curIndexA >= 0 || curIndexB >= 0){
 28         valueA = curIndexA < 0 ? 0 : addA[curIndexA];     // 真正進行運算的 valueA,valueB
 29         valueB = curIndexB < 0 ? 0 : addB[curIndexB]; 
 30 
 31         tempSum = valueA + valueB - 2*0;
 32         if(carry) tempSum = tempSum + 1;
 33 
 34         if(tempSum > 9){
 35             carry = 1;
 36             tempSum = tempSum % 10;
 37         }
 38         else carry = 0;
 39 
 40         tempResult[resultIndex] = tempSum + 0;
 41         resultIndex++;
 42         curIndexA--;
 43         curIndexB--;
 44     }
 45 
 46     if(carry)tempResult[resultIndex++] = 1;
 47     tempResult[resultIndex] = \0;
 48 
 49     int i = 0;
 50     for(resultIndex = resultIndex-1; resultIndex >= 0; ++i,--resultIndex){
 51         Result[i] = tempResult[resultIndex];
 52     }
 53     Result[i] = \0;
 54 
 55     delete []tempResult;
 56 }
 57 
 58 // Function void Sub(char subA[],char subB[]){
 59 // subA = subA - subB, 返回 subA
 60 // 留意比如 1 - 9, 得到負數,沒關系,最後取值是 (1-9)+10 = 2 
 61 // 註意借位設置 = true, 當借位 = true, 進行計算的value要-1,自行手工模擬即知
 62 void Sub(char subA[],char subB[]){
 63     int lengthB = strlen(subB);
 64     int lengthA = strlen(subA);
 65     int valueA,valueB,theirSub;
 66 
 67     int curIndexB = lengthB-1; 
 68     int curIndexA = lengthA-1;
 69     bool borrow = false;
 70 
 71     for(; curIndexA >= 0; --curIndexA,--curIndexB){
 72 
 73         valueA = (borrow == false) ? subA[curIndexA] - 0 : subA[curIndexA]-1 -0;
 74         valueB = curIndexB < 0 ? 0 : subB[curIndexB] - 0;
 75         theirSub = valueA - valueB;
 76         if(theirSub >= 0){
 77             borrow = false;
 78             subA[curIndexA] = theirSub + 0;
 79         }
 80         else{
 81             borrow = true;
 82             subA[curIndexA] = 10 + theirSub + 0;
 83         }
 84     }
 85 }
 86 
 87 void DisplayCharArray(char *Array){
 88     for(int i = 0; i < strlen(Array); ++i){
 89         cout<< Array[i];
 90     }
 91 }
 92 int main(){
 93 
 94     char *prenum = new char[5000];
 95     char *middle = new char[5000];
 96     char *perfectMethod = new char[5000];
 97     char *ArrayTempPoint = NULL;
 98     char *allMethod = new char[5000];   // 2^n
 99     prenum[0] = 2;
100     prenum[1] = \0;                   // 記得設置 ‘\0‘ 邊界
101     middle[0] = 4;
102     middle[1] = \0;
103 
104     int num;
105         cin>> num;
106 
107     for(int i = 2; i < num; ++i){       // 關鍵算法,計算完美數
108         Add(prenum,middle,perfectMethod);
109         ArrayTempPoint = prenum;
110         prenum = middle;
111         middle = perfectMethod;
112         if(i != num-1) perfectMethod = ArrayTempPoint;
113     }
114 
115     delete []ArrayTempPoint;
116     delete []prenum;
117     // TEST  Perfect Num
118     //cout<< "Perfect Num : "<<endl; DisplayCharArray(perfectMethod); cout<<endl;
119 
120     char *add1 = new char[5000];
121     add1[0] = 2;
122     add1[1] = \0;
123 
124 
125     for( int i = 1; i < num ; ++i){     // 利用加法實現求 2^n
126         Add(add1,add1,allMethod);
127         ArrayTempPoint = add1;
128         add1 = allMethod;
129         if(i != num-1){
130             allMethod = ArrayTempPoint;
131         }
132     }
133     delete []ArrayTempPoint;            // ArrayTempPoint,add1
134 
135     // TEST 2^n
136     //cout<< "2^n : "<<endl; DisplayCharArray(allMethod); cout<<endl;
137 
138 
139     Sub(allMethod,perfectMethod);       // 進行相減
140     bool start = false;
141     for(int i = 0; i < strlen(allMethod); ++i){     
142         if(allMethod[i] != 0)  start = true;
143         if(start == true && allMethod[i] != \0) cout<< allMethod[i];
144     }                                    // 註意為何我要這樣輸出 ?
145 
146     delete []perfectMethod;                // 內存清理
147     delete []allMethod;
148 
149     return 0;
150 
151 }
152 
153 
154 
155 /*********************************************************************
156    對於指針一定要細心 因為你幾乎是什麽都可以修改
157    比如 char *pChar = new char[100];
158    那麽系統默認 pChar[0] = ‘\0‘  你如果這時候擅自修改 pChar[0]
159    會使得這個數組丟失 ‘\0‘
160 *********************************************************************/
View Code

  

斐波那契 [ Fibonacci] 數列之大整數求和