2018年湘潭大学程序设计竞赛 G又见斐波那契

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

题目描述

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

输入描述:

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

输出描述:

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

输入

4
1
2
3
100

输出

1
16
57
558616258

题意: 构造一个6 * 6的矩阵, 即可。

f[i]        =       1 1 1 1 1 1             f[i-1]

f[i-1]     =      1 0 0 0 0 0              f[i-2]

(i+1)^3 =      0 0 1 3 3 1               i^3

(i+1)^2 =      0 0 0 1 2 1       *      i^2

i + 1      =      0 0 0 0 1 1              i

1            =     0 0 0 0 0 1              1

#include <bits/stdc++.h>

using namespace std;
using ll = long long;
const ll MOD = 1E9 + 7;
struct Matrix
{
    ll a[7][7];
    void clear() {
        memset(a, 0, sizeof(a));
    }
    void init() {
        clear();
        a[1][1]=a[2][2]=a[3][3]=a[4][4]=a[5][5]=a[6][6]=1;
    }
    void gao() {
        clear();
        for(int i = 1;i <= 6;i ++) a[1][i]=1;
        a[2][1]=1;
        a[3][3]=a[3][6]=1; a[3][4]=a[3][5]=3;
        a[4][4]=a[4][6]=1; a[4][5]=2;
        a[5][5]=a[5][6]=1;
        a[6][6]=1;
    }
    Matrix operator * (const Matrix & x) const {
        Matrix res;
        res.clear();
        for(int i = 1;i <= 6;i ++) {
            for(int k = 1;k <= 6;k ++) {
                if(a[i][k]) {
                    for(int j = 1;j <= 6;j ++) {
                        res.a[i][j] += a[i][k] * x.a[k][j];
                        if(res.a[i][j] >= MOD) res.a[i][j] %= MOD;
                    }
                }
            }
        }
        return res;
    }
    Matrix mpow(Matrix x, ll n) {
        Matrix res;
        res.init();
        while(n) {
            if(n & 1) res = res * x;
            x = x * x;
            n >>= 1;
        }
        return res;
    }
    void show() {
        for(int i = 1;i <= 6;i ++) {
            for(int j = 1;j <= 6;j ++) {
                printf("%lld ",a[i][j]);
            }puts("");
        }
    }
};
int main()
{
    int T;
    scanf("%d", &T);
    while(T --) {
        ll n;
        scanf("%lld", &n);
        if(n == 1) {
            puts("1");
        } else {
            Matrix res;
            res.gao();
            res = res.mpow(res, n - 1);
            ll t = 0;
            t += res.a[1][1];
            t += res.a[1][3] * 8;
            t %= MOD;
            t += res.a[1][4] * 4;
            t += res.a[1][5] * 2;
            t += res.a[1][6];
            printf("%lld\n", t % MOD);
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值