矩阵快速幂 - 湘潭大学

链接:https://www.nowcoder.com/acm/contest/105/G
来源:牛客网

题目描述

这是一个加强版的斐波那契数列。
给定递推式
求F(n)的值,由于这个值可能太大,请对109+7取模。

输入描述:

第一行是一个整数T(1 ≤ T ≤ 1000),表示样例的个数。
以后每个样例一行,是一个整数n(1 ≤ n ≤ 10
18
)。

输出描述:

每个样例输出一行,一个整数,表示F(n) mod 1000000007。
示例1

输入

4
1
2
3
100

输出

1
16
57
558616258

题意 : 一个比较裸的题,只要构造出来矩阵就很容易。

 



代码示例 :
#define ll long long
const ll maxn = 1e6+5;
const ll mod = 1000000007;
const double eps = 1e-9;
const double pi = acos(-1.0);
const ll inf = 0x3f3f3f3f;

ll n;
struct mat
{
    ll a[10][10];
};
const ll modulu[10][10] = {
    {1, 1, 1, 1, 1, 1},
    {1, 0, 0, 0, 0, 0},
    {0, 0, 1, 3, 3, 1},
    {0, 0, 0, 1, 2, 1},
    {0, 0, 0, 0, 1, 1},
    {0, 0, 0, 0, 0, 1}
};

mat mul(mat a, mat b){
    mat r;
    memset(r.a, 0, sizeof(r.a));
    
    for(ll i = 0; i < 6; i++){
        for(ll j = 0; j < 6; j++){
            for(ll k = 0; k < 6; k++){
                r.a[i][j] += (a.a[i][k]*b.a[k][j])%mod;
                r.a[i][j] %= mod;            
            }
        }
    }
    return r;
}

mat qpow(mat a, ll x){
    mat b;
    memset(b.a, 0, sizeof(b.a));
    for(ll i = 0; i <6; i++) b.a[i][i] = 1;
    
    while(x){
        if (x&1) b = mul(b, a);
        a = mul(a, a);
        x >>= 1;
    }
    return b;
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    ll t;
    
    cin >> t;
    while(t--){
        scanf("%lld", &n);
        mat a;
        memcpy(a.a, modulu, sizeof(modulu));
        if (n == 1) {printf("1\n"); continue;}
        else if (n == 0) {printf("0\n"); continue;} 
        //for(ll i = 0; i < 6; i++){
            //for(ll j = 0; j < 6; j++){
                //prllf("%d ", a.a[i][j]);
            //}
            //prllf("\n");
        //}
        a = qpow(a, n-1);
        ll sum = a.a[0][0]+a.a[0][2]*8+a.a[0][3]*4+a.a[0][4]*2+a.a[0][5];
        printf("%lld\n", sum%mod);
    }
    return 0;
}

 

posted @ 2018-04-30 15:45  楼主好菜啊  阅读(160)  评论(0编辑  收藏  举报