1. 程式人生 > >九度OJ題目1081:遞推數列解題報告

九度OJ題目1081:遞推數列解題報告

題目分析1:

一個很顯然的想法是遞推計算這k+1個數對10000的模,實現如下:

原始碼1(TLE)

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define MOD 10000
  4. int main()  
  5. {  
  6.     int a0, a1, p, q, k;  
  7.     while(scanf("%d%d%d%d%d", &a0, &a1, &p, &q, &k) != EOF)  
  8.     {  
  9.         int *pa = (int *)malloc(sizeof(int)*(k+1));  
  10.         pa[0] = a0;  
  11.         pa[1] = a1;  
  12.         int i;  
  13.         for(i = 2; i <= k; i++)                      //時間複雜度為O(k)
  14.             pa[i] = (p * pa[i-1] + q * pa[i-2])%MOD;  
  15.         printf("%d\n", pa[k]);  
  16.         free(pa);  
  17.     }  
  18.     //system("pause");
  19.     return 0;  
  20. }  
  21. /**************************************************************
     
  22.     Problem: 1081 
  23.     User: superlc320 
  24.     Language: C++ 
  25.     Result: Time Limit Exceed 
  26. ****************************************************************/

題目分析2:

很不幸,超時了。以上演算法的時間複雜度為O(k), 當k很大時,會TLE。再次分析題目,會發現遞推公式進而推出問題轉化為求這裡要用到 矩陣二分乘法。矩陣二分乘法是一種有效的快速計算矩陣冪的演算法。矩陣二分乘法通常可以將線性遞推問題O(n)時間縮短到O(log(n))。關於矩陣二分乘法更詳細的內容可以問度娘。

原始碼2

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define MOD 10000       //結果取MOD,避免高精度運算
  4. /*將矩陣p與矩陣q相乘,結果存入p矩陣*/
  5. void Matrix_mul(int p[2][2], int q[2][2])  
  6. {  
  7.     int i, j, k;  
  8.     int t[2][2]={0};  
  9.     for(i = 0; i <= 1; i++)  
  10.         for(j = 0; j <= 1; j++)  
  11.             for(k = 0; k <= 1; k++)  
  12.                 t[i][j] += p[i][k] * q[k][j];  
  13.     for(i = 0; i <= 1; i++)  
  14.         for(j = 0; j <= 1; j++)  
  15.             p[i][j] = t[i][j] % MOD;  
  16. }  
  17. /*計算p矩陣的n次方,結果存入p矩陣*/
  18. void Matrix_cal(int p[2][2], int n)  
  19. {  
  20.     int i, j;  
  21.     int t[2][2];  
  22.     for(i = 0; i <= 1; i++)  
  23.         for(j = 0; j <= 1; j++)  
  24.             t[i][j] = p[i][j];  
  25.     if(n == 1)   
  26.         return;  
  27.     elseif(n & 1)  
  28.     {  
  29.         Matrix_cal(p, n-1);  
  30.         Matrix_mul(p, t);  
  31.     }  
  32.     else
  33.     {  
  34.         Matrix_cal(p, n/2);  
  35.         Matrix_mul(p, p);  
  36.     }  
  37. }  
  38. int main()  
  39. {  
  40.     int a0, a1, p, q, k;  
  41.     while(scanf("%d%d%d%d%d", &a0, &a1, &p, &q, &k) != EOF)  
  42.     {  
  43.         if(k == 0)   
  44.             printf("%d\n", a0);    
  45.         elseif(k == 1)   
  46.             printf("%d\n", a1);   
  47.         else
  48.         {  
  49.             int matrix[2][2] = { {p%MOD, q%MOD}, {1, 0} };  
  50.             Matrix_cal(matrix, k-1);  
  51.             printf("%d\n", (a1 * matrix[0][0] + a0 * matrix[0][1]) % MOD);  
  52.         }  
  53.     }  
  54.     //system("pause");
  55.     return 0;  
  56. }  
  57. /************************************************************** 
  58.     Problem: 1081 
  59.     User: superlc320 
  60.     Language: C++ 
  61.     Result: Accepted 
  62.     Time:10 ms 
  63.     Memory:1020 kb 
  64. ****************************************************************/