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;
}

 

posted @ 2018-07-20 14:45  KirinSB  阅读(177)  评论(0编辑  收藏  举报