程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> NYOJ 1075 (遞推 + 矩陣快速冪)

NYOJ 1075 (遞推 + 矩陣快速冪)

編輯:C++入門知識

NYOJ 1075 (遞推 + 矩陣快速冪)


“紅色病毒”問題

時間限制:1000 ms | 內存限制:65535 KB 難度:4
描述
醫學研究者最近發現了一種新病毒,因為其蔓延速度與曾經在Internet上傳播的“紅色代碼”不相上下,故被稱為“紅色病毒”。 經研究發現,該病毒及其變種的DNA序列中,腺嘌呤(A)、胞嘧啶(C)均是成對出現的。LYH想知道在這種特征下,所有可能成為該病毒的DNA序列的個數。
輸入
多組測試數據。 每組數據輸入一個整數n,表示該病毒DNA序列的長度。(1≤n≤10^9) n=0時表示輸入結束,不用做任何處理。
輸出
每組輸出占一行,代表該病毒長度為n的所有可能的DNA序列個數。由於結果可能非常大,你只需輸出對10007取余後的結果即可。
樣例輸入
12
樣例輸出
26
提示
DNA序列僅由腺嘌呤(A),鳥嘌呤(G),胞嘧啶(C),胸腺嘧啶(T)四種核苷酸組成。 當n=2時,所有可能的DNA序列為TT、TG、GT、GG、AA、CC。


分析:因為題目要求A和C要成對出現,即A和C的數量都是偶數,所以可以定義4個狀態:
dp[n][0]表示長度為n時A的數量為偶數,C的數量也為偶數,
dp[n][1]表示長度為n時A的數量為偶數,C的數量為奇數,
dp[n][2]表示長度為n時A的數量為奇數,C的數量為偶數,
dp[n][3]表示長度為n時A的數量為奇數,C的數量也為奇數的DNA序列的數量,
dp[n][0] = dp[n-1][0] * 2 + dp[n-1][1] * 1 + dp[n-1][2] * 1 + dp[n-1][3] * 0
dp[n][1] = dp[n-1][0] * 1 + dp[n-1][1] * 2 + dp[n-1][2] * 0 + dp[n-1][3] * 1
dp[n][2] = dp[n-1][0] * 1 + dp[n-1][1] * 0 + dp[n-1][2] * 2 + dp[n-1][3] * 1
dp[n][3] = dp[n-1][0] * 0 + dp[n-1][1] * 1 + dp[n-1][2] * 1 + dp[n-1][3] * 2
根據這個遞推關系,可以構造出如下一個4*4的矩陣,
| 2 1 1 0 |
| 1 2 0 1 |
| 1 0 2 1 |
| 0 1 1 2 |
然後利用矩陣快速冪就可以快速求出答案。
#include
#include

#define mod 10007

struct Matrix {
    int mat[4][4];
    Matrix() {
        memset(mat, 0, sizeof(mat));
        for(int i = 0; i < 4; i++)
            mat[i][i] = 1;
    }
};

Matrix Multi(Matrix a, Matrix b) {
    Matrix res;
    for(int i = 0; i < 4; i++) {
        for(int j = 0; j < 4; j++) {
            res.mat[i][j] = 0;
            for(int k = 0; k < 4; k++) {
                res.mat[i][j] += a.mat[i][k] * b.mat[k][j];
                res.mat[i][j] %= mod;
            }
        }
    }
    return res;
}

Matrix Pow(Matrix a, int x) {
    Matrix res;
    while(x) {
        if(x&1) res = Multi(res, a);
        a = Multi(a, a);
        x >>= 1;
    }
    return res;
}

int main() {
    int T, n;

    Matrix A;  //系數矩陣
    A.mat[0][0] = 2; A.mat[0][1] = 1; A.mat[0][2] = 1; A.mat[0][3] = 0;
    A.mat[1][0] = 1; A.mat[1][1] = 2; A.mat[1][2] = 0; A.mat[1][3] = 1;
    A.mat[2][0] = 1; A.mat[2][1] = 0; A.mat[2][2] = 2; A.mat[2][3] = 1;
    A.mat[3][0] = 0; A.mat[3][1] = 1; A.mat[3][2] = 1; A.mat[3][3] = 2;

    scanf("%d",&T);
    while(T--) {
        scanf("%d", &n);
        Matrix ans = Pow(A, n);
        printf("%d\n", ans.mat[0][0]);
    }

    return 0;
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved