CodeForces 450B Jzzhu and Sequences(矩陣快速冪)題解

思路:

之前那篇完全沒想清楚,給刪了,下午一上班突然想明白了。

講一下這道題的大概思路,應該就明白矩陣快速冪是怎麼回事了。

我們首先可以推導出

\binom{1\, \, \, \, \, \, -1}{1\,\,\,\,\,\, \, \, \, \, 0}*\binom{f[n-1]}{f[n-2]}=\binom{f[n]}{f[n-1]}

學過矩陣的都應該看得懂,我們把它簡寫成T*A(n-1)=A(n),是不是有點像等比?然後我們得到T^(n-1)*A(1)=A(n),所以我們可以通過矩陣快速冪快速計算左邊的T^n-1這個式子,最後再和A1相乘,那麼第一個數字就是答案了。

代碼:

#include<set>
#include<cstring>
#include<cstdio>
#include<algorithm>
const int maxn = 2;
const int MOD = 1000000000+7;
const int INF = 0x3f3f3f3f;
using namespace std;
struct Mat{
    int s[maxn][maxn];
    void init(){
        for(int i = 0;i < maxn;i++)
            for(int j = 0;j < maxn;j++)
                s[i][j] = 0;
    }
};

Mat mul(Mat a,Mat b){
    Mat t;
    t.init();
    for(int i = 0;i < maxn;i++){
        for(int j = 0;j < maxn;j++){
            for(int k = 0;k < maxn;k++){
                t.s[i][j] = (t.s[i][j] + a.s[i][k]*b.s[k][j])%MOD;
            }
        }
    }
    return t;
}
Mat pow_mat(Mat p,int n){
    Mat ret;
    ret.init();
    ret.s[0][0] = ret.s[1][1] = 1;
    while(n){
        if(n & 1) ret = mul(ret,p);
        p = mul(p,p);
        n >>= 1;
    }
    return ret;
}
int main(){
    int x,y,n;
    Mat a;
    a.s[0][0] = 1;
    a.s[0][1] = -1;
    a.s[1][0] = 1;
    a.s[1][1] = 0;
    scanf("%d%d%d",&x,&y,&n);
    if(n == 1){
        printf("%d\n",(x%MOD + MOD)%MOD);
    }
    else if(n == 2){
        printf("%d\n",(y%MOD + MOD)%MOD);
    }
    else{
        a = pow_mat(a,n - 2);
        printf("%d\n",((y*a.s[0][0] + x*a.s[0][1])%MOD +MOD)%MOD);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章