算法習題——矩陣

Q1(poj 3070):ios

求斐波那契數列的第n個,n最大取到1000000000,編程

分析:求這種較大遞推數列的通常方法使用矩陣快速冪的,這裏題目直接給出了矩陣形式,就不須要進行友矩陣(A)的構造了,也不須要進行最後一次矩陣和向量的相乘,直接初始化矩陣規模,進行快速冪便可。數組

不過這個結論卻是能夠記住,之後就有了logn求斐波那契數列的方法:ide

參考代碼以下:函數

 

#include<iostream>
#include<string>
#include<cstring>
using namespace std;

const int maxn = 20;
typedef long long Matrix[maxn][maxn];
typedef long long Vector[maxn];

int sz , mod;
void matrix_mul(Matrix A , Matrix B , Matrix res)//矩陣A*B = C , O(n^3).矩陣均爲同階方陣
{
     Matrix C;
     memset(C , 0 , sizeof(C));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz; j++)
             for(int k = 0;k < sz; k++)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j])%mod;

     memcpy(res , C , sizeof(C));
}
void matrix_pow(Matrix A , int n , Matrix res)//矩陣快速冪O(logn)
{
    Matrix a , r;
    memcpy(a , A , sizeof(a));
    memset(r , 0 , sizeof(r));
    for(int i = 0;i < sz;i++)  r[i][i] = 1;//單位矩陣
    while(n){
        if(n&1)  matrix_mul(r , a , r);
        n >>= 1;
        matrix_mul(a , a , a);
    }
    memcpy(res , r , sizeof(r));
}

void Transform(Vector d , Matrix A , Vector res)//計算完A^(n-d)以後,這個函數計算A*d = res
{
     Vector r;
     memset(r , 0 , sizeof(r));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz;j++)
              r[i]  = (r[i] + d[j] * A[i][j])%mod;

     memcpy(res , r , sizeof(r));
}

int main()
{
    int  n;
    while(cin >>n)
    {
         if(n == -1) break;
         if(n == 0) {cout<<0<<endl;continue;}

         mod = 10000;
         sz = 2;

         Vector a , f;
         Matrix A;
         memset(A , 0 , sizeof(A));
         A[0][0] = 1;
         A[0][1] = 1;
         A[1][0] = 1;
         A[1][1] = 0;

         matrix_pow(A , n - 1 , A);
         cout << A[0][0] << endl;
    }
    return 0;
}

 

 

Q2(hdu 5950):優化

一個數列的遞推關係式是f[i] = f[i-1] + 2f[i-2] + i^4,如今給出n(最大可取1000000000),計算f[n]%mod的結果。ui

分析:這道題的核心方法就是上面咱們提到的時間複雜度爲O(logn)求遞推關係的矩陣快速冪。而這個方法的關鍵就是快速冪的底數A,須要必定的推導技巧。spa

#include<iostream>
#include<string>
#include<cstring>
using namespace std;

const int maxn = 20;
typedef long long Matrix[maxn][maxn];
typedef long long Vector[maxn];

int sz ;
long long mod = 2147493647;
void matrix_mul(Matrix A , Matrix B , Matrix res)//矩陣A*B = C , O(n^3).矩陣均爲同階方陣
{
     Matrix C;
     memset(C , 0 , sizeof(C));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz; j++)
             for(int k = 0;k < sz; k++)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j])%mod;

     memcpy(res , C , sizeof(C));
}
void matrix_pow(Matrix A , int n , Matrix res)//矩陣快速冪O(logn)
{
    Matrix a , r;
    memcpy(a , A , sizeof(a));
    memset(r , 0 , sizeof(r));
    for(int i = 0;i < sz;i++)  r[i][i] = 1;//單位矩陣
    while(n){
        if(n&1)  matrix_mul(r , a , r);
        n >>= 1;
        matrix_mul(a , a , a);
    }
    memcpy(res , r , sizeof(r));
}

void Transform(Vector d , Matrix A , Vector res)//計算完A^(n-d)以後,這個函數計算A*d = res
{
     Vector r;
     memset(r , 0 , sizeof(r));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz;j++)
              r[i]  = (r[i] + d[j] * A[i][j])%mod;

     memcpy(res , r , sizeof(r));
}

int main()
{
    long long n , a , b;

     int t;
     cin>>t;
    while(t--)
    {
       cin>>n>>a>>b;
      sz = 7;             //矩陣A的規模是sz
      Vector  f;
      if(n == 1) {cout<<a<<endl;continue;}
      if(n == 2) {cout<<b<<endl;continue;}
         f[0] = b;f[1] = a;
         f[2] = 16;f[3] = 8;f[4] = 4;f[5] = 2;f[6] = 1;

     Matrix A;
     memset(A , 0 , sizeof(A));//注意每次矩陣A的參數都要初始化.
     A[0][0] = 1;A[0][1] = 2;A[0][2] = 1;A[0][3] = 4;A[0][4] = 6;A[0][5] = 4;A[0][6] = 1;
     A[1][0] = 1;
     A[2][2] = 1;A[2][3] = 4;A[2][4] = 6;A[2][5] = 4;A[2][6] = 1;
     A[3][3] = 1;A[3][4] = 3;A[3][5] = 3;A[3][6] = 1;
     A[4][4] = 1;A[4][5] = 2;A[4][6] = 1;
     A[5][5] = 1;A[5][6] = 1;
     A[6][6] = 1;

         matrix_pow(A , n - 2 , A);
         Transform(f , A , f);

         cout << f[0] << endl;
    }
    return 0;
} 

Q3(uva 10689):3d

 這道題目是矩陣快速冪求斐波那契數列的推廣形式,給出f[0],f[1]的初值,遞推關係式斐波那契數列的遞推關係f[n]=f[n-1]+f[n-2].code

  分析:因爲遞推關係和斐波那契數列的遞推關係一致,友矩陣Q是同樣的.

 

 

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
using namespace std;

const int maxn = 20;
typedef long long Matrix[maxn][maxn];
typedef long long Vector[maxn];

int sz , mod;
void matrix_mul(Matrix A , Matrix B , Matrix res)//矩陣A*B = C , O(n^3).矩陣均爲同階方陣
{
     Matrix C;
     memset(C , 0 , sizeof(C));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz; j++)
             for(int k = 0;k < sz; k++)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j])%mod;

     memcpy(res , C , sizeof(C));
}
void matrix_pow(Matrix A , int n , Matrix res)//矩陣快速冪O(logn)
{
    Matrix a , r;
    memcpy(a , A , sizeof(a));
    memset(r , 0 , sizeof(r));
    for(int i = 0;i < sz;i++)  r[i][i] = 1;//單位矩陣
    while(n){
        if(n&1)  matrix_mul(r , a , r);
        n >>= 1;
        matrix_mul(a , a , a);
    }
    memcpy(res , r , sizeof(r));
}

void Transform(Vector d , Matrix A , Vector res)//計算完A^(n-d)以後,這個函數計算A*d = res
{
     Vector r;
     memset(r , 0 , sizeof(r));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz;j++)
              r[i]  = (r[i] + d[j] * A[i][j])%mod;

     memcpy(res , r , sizeof(r));
}

int main()
{
   int a , b , m , n;
   int t;
   cin>>t;
   while(t--)
  {
      cin >> a >> b >> n >>m;
      mod = 10;
      sz = 2;
      for(int i = 1;i < m;i++)
             mod *= 10;

      Vector  f;
      Matrix A;


       f[1] = a;
       f[0] = b;
         //列向量[f(d) , f(d-1) , f(d-2) , ... , f(1)]

       memset(A , 0 , sizeof(A));//獲得配出來的常數矩陣A
       A[0][0] = 1;A[0][1] = 1;
       A[1][0] = 1;A[1][1] = 0;

       matrix_pow(A , n - 1 , A);
       Transform(f , A , f);


         cout << f[0] << endl;
  }

    return 0;
}
View Code

 

Q4(hdu4565):

 

Q5(hdu2256)

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
using namespace std;

const int maxn = 20;
typedef long long Matrix[maxn][maxn];
typedef long long Vector[maxn];

int sz , mod;
void matrix_mul(Matrix A , Matrix B , Matrix res)//矩陣A*B = C , O(n^3).矩陣均爲同階方陣
{
     Matrix C;
     memset(C , 0 , sizeof(C));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz; j++)
             for(int k = 0;k < sz; k++)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j])%mod;

     memcpy(res , C , sizeof(C));
}
void matrix_pow(Matrix A , int n , Matrix res)//矩陣快速冪O(logn)
{
    Matrix a , r;
    memcpy(a , A , sizeof(a));
    memset(r , 0 , sizeof(r));
    for(int i = 0;i < sz;i++)  r[i][i] = 1;//單位矩陣
    while(n){
        if(n&1)  matrix_mul(r , a , r);
        n >>= 1;
        matrix_mul(a , a , a);
    }
    memcpy(res , r , sizeof(r));
}

void Transform(Vector d , Matrix A , Vector res)//計算完A^(n-d)以後,這個函數計算A*d = res
{
     Vector r;
     memset(r , 0 , sizeof(r));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz;j++)
              r[i]  = (r[i] + d[j] * A[i][j])%mod;

     memcpy(res , r , sizeof(r));
}

int main(){
    int n , T;
    scanf("%d" , &T);
    while(T--){
         scanf("%d" , &n);
         mod = 1024;//整個數值在m的剩餘系下
         sz = 2;//矩陣A的規模是sz
        if(n == 0) {printf("1\n");continue;}
         Vector a , f;
         Matrix A;
         //A是矩陣,a是遞推公式的係數向量 f是數列的初值向量
         f[0] = 1; f[1] = 0;
         //列向量[f(d) , f(d-1) , f(d-2) , ... , f(1)]
         //數學概念上向量從1開始,可是存儲上f[]數組是從0開始的,這點必定要注意!!邏輯高位存儲在存儲結構的地位,這裏很是容易錯!
         memset(A , 0 , sizeof(A));//獲得配出來的常數矩陣A
         A[0][0] = 5;A[0][1] = 12;
         A[1][0] = 2;A[1][1] = 5;


         matrix_pow(A , n  , A);
         Transform(f , A , f);


        printf("%d\n" ,(2 * f[0] - 1) %mod);
    }
    return 0;
}
View Code

Q6(hdu5451):

 

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
using namespace std;

const int maxn = 20;
typedef long long Matrix[maxn][maxn];
typedef long long Vector[maxn];
typedef long long LL;
int sz , mod;
void matrix_mul(Matrix A , Matrix B , Matrix res)//矩陣A*B = C , O(n^3).矩陣均爲同階方陣
{
     Matrix C;
     memset(C , 0 , sizeof(C));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz; j++)
             for(int k = 0;k < sz; k++)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j])%mod;

     memcpy(res , C , sizeof(C));
}
void matrix_pow(Matrix A , int n , Matrix res)//矩陣快速冪O(logn)
{
    Matrix a , r;
    memcpy(a , A , sizeof(a));
    memset(r , 0 , sizeof(r));
    for(int i = 0;i < sz;i++)  r[i][i] = 1;//單位矩陣
    while(n){
        if(n&1)  matrix_mul(r , a , r);
        n >>= 1;
        matrix_mul(a , a , a);
    }
    memcpy(res , r , sizeof(r));
}

void Transform(Vector d , Matrix A , Vector res)//計算完A^(n-d)以後,這個函數計算A*d = res
{
     Vector r;
     memset(r , 0 , sizeof(r));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz;j++)
              r[i]  = (r[i] + d[j] * A[i][j])%mod;

     memcpy(res , r , sizeof(r));
}
LL Quick_Mod(LL a, LL b, int m){
    LL res = 1,term = a % m;
    while(b)
    {
        if(b & 1) res = (res * term) % m;
        term = (term * term) % m;
        b >>= 1;
    }
    return res%m;

}

int main(){
    int  T;
    LL x;
    scanf("%d" , &T);
    for(int kase = 1;kase <= T;kase++){
         scanf("%lld %d" , &x , &mod);
         sz = 2;//矩陣A的規模是sz
          Vector a , f;
          Matrix A;
          //A是矩陣,a是遞推公式的係數向量 f是數列的初值向量
          f[0] = 1; f[1] = 0;
          x = Quick_Mod(2 , x ,  mod * mod - 1) + 1;
          if(x == 0) {printf("1\n");continue;}

         //列向量[f(d) , f(d-1) , f(d-2) , ... , f(1)]
         //數學概念上向量從1開始,可是存儲上f[]數組是從0開始的,這點必定要注意!!邏輯高位存儲在存儲結構的地位,這裏很是容易錯!
         memset(A , 0 , sizeof(A));//獲得配出來的常數矩陣A
         A[0][0] = 5;A[0][1] = 12;
         A[1][0] = 2;A[1][1] = 5;


         matrix_pow(A , x , A);
         Transform(f , A , f);


        printf("Case #%d: %d\n" ,kase , (2 * f[0] - 1) %mod);
    }
    return 0;
} 
View Code

Q7(hdu6198):

  基於斐波那契數列,給出整數k,讓你計算k個容許重複的斐波那契數列,不能組成的最小整數是多少。

  分析:經過手動算找規律,編程打表找規律也好,找到規律問題的本質是讓咱們求fib(2n + 3)-1.而後簡單一發矩陣快速冪便可。

 

 

Q8(hdu6185):

1x2的格子覆蓋4xn的格子,問有多少種不一樣的方案,結果對1e9+7取模。

分析:這道題目算是很綜合了。純粹基於覆蓋的機理找遞推關係難度較大,能夠經過dfs找到小數據的表,咱們根據n的取值,也可以猜想這道題目應該是有線性遞推的關係的。這裏在拿到了前十項的數據以後,找規律有個小套路,最基本的是靠觀察,可是對於含有2項以上的線性遞推關係,這個方法就不是很好了。這裏咱們依次假設題目有以下的線性遞推關係:

(1)f(n) = a*f(n-1)+b*f(n-2)

(2)f(n) = a*f(n-1)+b*f(n-2)+c*f(n-3)

(3)f(n)=a*f(n-1)+b*f(n-2)+c*f(n-3)+d*f(n-4)

...

 

而後基於原始數據,構造線性方程組再用高斯消元求解ab等參數進行驗證,當獲得係數均爲整數的時候,即題目知足的線性遞推關係。

找到了線性遞推關係以後,用矩陣快速冪跑一發便可。

 

 Q9(hdu4965):

 

 

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
using namespace std;

const int maxn = 1000 + 1;
typedef long long Matrix1[maxn][6];
typedef long long Matrix2[6][maxn];
typedef long long Matrix3[6][6];


int sz , mod;
void matrix_mul(Matrix3 A , Matrix3 B , Matrix3 res)//矩陣A*B = C , O(n^3).矩陣均爲同階方陣
{
     Matrix3 C;
     memset(C , 0 , sizeof(C));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz; j++)
             for(int k = 0;k < sz; k++)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j])%mod;

     memcpy(res , C , sizeof(C));
}

void matrix_mul_p1(Matrix2 B ,  Matrix1 A, int sz1 , int sz2, int sz3 ,  Matrix3 res){//sz1*sz2的矩陣與sz2*sz3的矩陣作乘法
       Matrix3 C;
       memset(C , 0 , sizeof(C));
       for(int i = 0;i < sz1;i++)
         for(int j = 0;j < sz3;j++)
            for(int k = 0;k < sz2;k++)
               C[i][j] = (C[i][j] + B[i][k]*A[k][j]);
         memcpy(res , C , sizeof(C));

}
void matrix_mul_p2(Matrix1 A ,  Matrix3 C, int sz1 , int sz2, int sz3 ,  Matrix1 res){//sz1*sz2的矩陣與sz2*sz3的矩陣作乘法
       Matrix1 temp;
       memset(temp , 0 , sizeof(temp));
       for(int i = 0;i < sz1;i++)
         for(int j = 0;j < sz3;j++)
            for(int k = 0;k < sz2;k++)
               temp[i][j] = (temp[i][j] + A[i][k]*C[k][j])%mod;
         memcpy(res , temp , sizeof(temp));

}

int matrix_mul_p3(Matrix1 A ,  Matrix2 B, int sz1 , int sz2, int sz3){//sz1*sz2的矩陣與sz2*sz3的矩陣作乘法
       int temp ,ans;
       temp = 0;ans = 0;
       for(int i = 0;i < sz1;i++){
         for(int j = 0;j < sz3;j++){
                temp = 0;
            for(int k = 0;k < sz2;k++)
               temp = (temp + A[i][k]*B[k][j])%mod;
            ans += temp;
         }
       }

        return ans;

}
void matrix_pow(Matrix3 A , int n , Matrix3 res)//矩陣快速冪O(logn)
{
    Matrix3 a , r;
    memcpy(a , A , sizeof(a));
    memset(r , 0 , sizeof(r));
    for(int i = 0;i < sz;i++)  r[i][i] = 1;//單位矩陣
    while(n){
        if(n&1)  matrix_mul(r , a , r);
        n >>= 1;
        matrix_mul(a , a , a);
    }
    memcpy(res , r , sizeof(r));
}



int main(){

         int n , k;
         while(scanf("%d%d" , &n , &k)){
            Matrix1 A;
            Matrix2 B;
            Matrix3 C;
            mod = 6;
            for(int i = 0;i < n;i++)
                 for(int j = 0;j < k;j++)
                    scanf("%lld" , &A[i][j]);

            for(int i = 0;i < k;i++)
                  for(int j = 0;j < n;j++)
                    scanf("%lld" , &B[i][j]);

            matrix_mul_p1(B , A , k , n , k , C);

            sz = k;
            matrix_pow(C , n*n - 1, C);


            //下面要作n*k的A  * k*k的C * k*n的B
           matrix_mul_p2(A , C , n , k , k , A);
           int ans = matrix_mul_p3(A , B , n , k , n);
            printf("%d\n" , ans);
         }



    return 0;
}
//lrj的快速冪模板迷之超時,下面貼一個ac代碼
/*
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <cctype>
using namespace std;

const int mod=6;
struct matrix{
    int f[6][6];
};
int A[1001][6],B[6][1001],C[1001][6],D[1001][1001];
matrix mul(matrix a,matrix b,int n)
{
    matrix c;
    memset(c.f,0,sizeof(c.f));
    int i,j,k;
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            for(k=0;k<n;k++)
            {
                c.f[i][j]+=a.f[i][k]*b.f[k][j];
            }
            c.f[i][j]%=mod;
        }
    }
    return c;
}
matrix pow_mod(matrix a,int b,int n)
{
    matrix s;
    memset(s.f,0,sizeof(s.f));
    for(int i=0;i<n;i++)s.f[i][i]=1;
    while(b)
    {
        if(b&1)s=mul(s,a,n);
        a=mul(a,a,n);
        b=b>>1;
    }
    return s;
}
int main()
{
    int n,K;
    while(scanf("%d%d",&n,&K)!=EOF)
    {
        if(n==0&&K==0)break;
        int i,j,k;
        for(i=0;i<n;i++)
            for(j=0;j<K;j++)
                scanf("%d",&A[i][j]);
        for(i=0;i<K;i++)
            for(j=0;j<n;j++)
                scanf("%d",&B[i][j]);
        matrix e,g;
        memset(e.f,0,sizeof(e.f));
        for(i=0;i<K;i++)
        {
            for(j=0;j<K;j++)
            {
                for(k=0;k<n;k++)
                    e.f[i][j]+=B[i][k]*A[k][j];
                e.f[i][j]%mod;
            }
        }
        e=pow_mod(e,n*n-1,K);
            for(int i = 0;i < K;i++){
              for(int j  =0;j < K;j++)
                  printf("%d " , e.f[i][j]);
           printf("\n");
         }
        memset(C,0,sizeof(C));
        for(i=0;i<n;i++)
        {
            for(j=0;j<K;j++)
            {
                for(k=0;k<K;k++)
                    C[i][j]+=A[i][k]*e.f[k][j];
                C[i][j]%=mod;
            }
        }
         for(int i = 0;i < n;i++){
              for(int j  =0;j < K;j++)
                  printf("%d " , C[i][j]);
           printf("\n");
         }
        int ans=0;
        memset(D,0,sizeof(D));
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                for(k=0;k<K;k++)
                    D[i][j]+=C[i][k]*B[k][j];
                ans+=D[i][j]%mod;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
*/
View Code

 

 Q10(hdu4990):

 利用題目給出的代碼所呈現的機制,輸入nm輸出對應的答案。

  分析:這是一個典型的優化代碼題目。可以看到mmod運算使用的,能夠不考慮。而後對於不一樣的n,咱們經過題目給出的程序能夠獲得n[0,11]的答案。

a[n]:0 1 2 5 10 21 42 85 170 341 682 1365.

題目其實就是快速求解這個數列.根據觀察得,這個數列知足f[n] = f[n-1]+2f[n-2]+1的遞推關係。而後矩陣快速冪構造一發便可。

 

#include<cstdio>
#include<string>
#include<cstring>
using namespace std;

const int maxn = 20;
typedef long long Matrix[maxn][maxn];
typedef long long Vector[maxn];

int sz , mod;
void matrix_mul(Matrix A , Matrix B , Matrix res)//矩陣A*B = C , O(n^3).矩陣均爲同階方陣
{
     Matrix C;
     memset(C , 0 , sizeof(C));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz; j++)
             for(int k = 0;k < sz; k++)
                C[i][j] = (C[i][j] + A[i][k] * B[k][j])%mod;

     memcpy(res , C , sizeof(C));
}
void matrix_pow(Matrix A , int n , Matrix res)//矩陣快速冪O(logn)
{
    Matrix a , r;
    memcpy(a , A , sizeof(a));
    memset(r , 0 , sizeof(r));
    for(int i = 0;i < sz;i++)  r[i][i] = 1;//單位矩陣
    while(n){
        if(n&1)  matrix_mul(r , a , r);
        n >>= 1;
        matrix_mul(a , a , a);
    }
    memcpy(res , r , sizeof(r));
}

void Transform(Vector d , Matrix A , Vector res)//計算完A^(n-d)以後,這個函數計算A*d = res
{
     Vector r;
     memset(r , 0 , sizeof(r));
     for(int i = 0;i < sz;i++)
          for(int j = 0;j < sz;j++)
              r[i]  = (r[i] + d[j] * A[i][j])%mod;

     memcpy(res , r , sizeof(r));
}

int main(){
    int n , m;
    while(~scanf("%d%d" , &n ,&m)){

         mod = m;sz = 4;

         Vector a , f;
         Matrix A;

         f[0] = 2;
         f[1] = 1;
         f[2] = 0;
         f[3] = 1;
         memset(A , 0 , sizeof(A));
         A[0][0] = 1;A[0][1] = 2;A[0][2] = 0;A[0][3] = 1;
         A[1][0] = 1;A[1][1] = 0;A[1][2] = 0;A[1][3] = 0;
         A[2][0] = 0;A[2][1] = 1;A[2][2] = 0;A[2][3] = 0;
         A[3][0] = 0;A[3][1] = 0;A[3][2] = 0;A[3][3] = 1;

         if(n ==0)       {printf("0\n");            continue;}
         else if(n == 1) {printf("%d\n" , 1 % mod); continue;}
         else if(n == 2) {printf("%d\n" , 2 % mod); continue;}
         matrix_pow(A , n - 2 , A);
         Transform(f , A , f);
         printf("%d\n" , f[0]);
    }
    return 0;
}
View Code

  固然還有比較傻瓜的作法是,根據手頭的數據,推測線性遞推關係而後構造線性方程組再用高斯消元(上文一個題目用到過)。這裏值得注意的是,推測線性遞推關係中,應該考慮常數項的,這樣相對上面(Q8:hdu6185),實際就是多了一個自變量。

  高斯消元的代碼以下:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=105;
typedef double Matrix[maxn][maxn];
Matrix A,S;
//n是方程的個數
void gauss(Matrix A,int n){
    int i,j,k,r;
    for(int i=0; i<n; i++)
    {
        r=i;
        for( j=i+1; j<n; j++)
            if(fabs(A[j][i])>fabs(A[r][i]))r=j;
        if(r!=i)
            for(j=0; j<=n; j++)swap(A[r][j],A[i][j]);
        for(k=i+1; k<n; k++)
        {
            double f=A[k][i]/A[i][i];
            for(j=i; j<=n; j++)
                A[k][j]-=f*A[i][j];
        }
    }
    for(i=n-1; i>=0; i--)
    {
        for(j=i+1; j<n; j++)
            A[i][n]-=A[j][n]*A[i][j];
        A[i][n]/=A[i][i];
    }
}
int main()
{

    memset(A,0,sizeof(A));
    A[0][0]=1,A[0][1]=0,A[0][2]=1;
    A[1][0]=2,A[1][1]=1,A[1][2]=1;
    A[2][0]=5,A[2][1]=2,A[2][2]=1;
    //對於線性方程組Ax = b 代碼中的A是[A,b]
    A[0][3]=2,A[1][3]=5,A[2][3]=10;
    gauss(A,3);
    //通過該代碼實現的高斯消元,解向量x是A矩陣的最後一列,即替代了原來的係數向量
    for(int i=0; i<3; i++)
        printf("%8.2f\n",A[i][3]);

    return 0;
}
View Code

  可求方程組的解集是[1,2,1],對應着咱們構造線性方程組的方式,可獲得遞推關係:f[n] = f[n-1] + 2f[n-2]+1.

相關文章
相關標籤/搜索