標籤:
http://acm.hdu.edu.cn/showproblem.php?pid=1041
有一個初始只有一個1的串 每次都按①0 -> 10;②1 -> 01;這兩條規則進行替換
形如:n = 1 1
n = 2 01
n = 3 1001
...
求經過n步替換之後 串中只含複數個0的連續子串(不難發現,這種子串只能是‘00’)的出現次數
因為0<n<=1000的限制 在最壞情況下(n==1000)串的長度將達到2^1000位 排除了直接類比上述替換過程的可能
列出前幾項的替換結果:
n = 0 1 ‘00’=0 ‘01’=0
n = 1 01 ‘00’=0 ‘01’=1
n = 2 1001 ‘00’=1 ‘01’=0
n = 3 01101001 ‘00’=1 ‘01’=2
n = 4 1001011001101001 ‘00’=3 ‘01’=2
n = 5 01101001100101101001011001101001 ‘00’=5 ‘01’=6
在上面的資料 不僅給出結果串 還統計出了串中‘00’對和‘01’對的個數【註:‘01’的個數是取出全部的‘00’對後才統計】
從n = 3開始 觀察可以發現 01 -> 1001 即每個00對(1001)都是由01對轉化而來
而每個00對(1001)又將產生一個 00對 和 兩個 01對(見n=2->3)
由上述可得 n步時00對的個數 = n-1步的00對的個數 + n-1的01對的個數(即n-2步的00對的個數 * 2)
所以可以推得 f(n) = f(n - 1) + f(n - 2) * 2
如果細心的話,可以發現,當n大到一定程度時,由於上面給出的公式有著與斐波拉契數列相似的遞增效應, 最終結果的數值會非常大大大大大,用__int64都遠遠無法滿足
所以採用字元數組來類比大數加法運算
# include <stdio.h># include <string.h># define MAX 1001# define LEN 1001char Number[MAX][LEN];void BigNumPlus(){for(int i = 3; i < MAX; i++){memset(Number[i], ‘0‘, LEN);//初始化for(int j = 0; j < LEN; j++)//類比公式{Number[i][j] += (Number[i - 1][j] - ‘0‘) + (Number[i - 2][j] - ‘0‘) + (Number[i - 2][j] - ‘0‘);}for(int j = 0; j < LEN; j++)//處理進位{if(Number[i][j] > ‘9‘){Number[i][j + 1] += (Number[i][j] - ‘0‘) / 10;Number[i][j] = (Number[i][j] - ‘0‘) % 10 + ‘0‘;}}}}int main(){//初始值memset(Number[1], ‘0‘, LEN);memset(Number[2], ‘0‘, LEN);Number[1][0] = ‘0‘;Number[2][0] = ‘1‘;BigNumPlus();int n;while(scanf("%d",&n) != EOF){if(n == 1)//特殊處理{printf("0\n");continue;}for(int i = LEN - 1; i >= 0; i--){if(Number[n][i] != ‘0‘)//格式輸出{while(i >= 0) printf("%c",Number[n][i--]);printf("\n");break;}}}return 0;}
HDOJ-1041 Computer Transformation(找規律+大數運算)