wmjxoj - 1050: QAQ的公式求解(二)【快速幂 + 矩阵】

题目传送门

矩阵加快速幂运算才发现这么好用。

根据递推公式f(i+1) = fi + (i+1)*(i+1) + (i+1)构造矩阵

| f(i) + (i+1)*(i+1) + (i+1) |                  | 1    1    1    0 |        |      f(1)      |

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

|              i + 2                 |                  | 0     0    1    1|        |     i + 1      |

|                 1                   |                  | 0     0    0    1|        |        1        |

就ok了。

#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
#include <stack>
#include <cmath>
#include <string>
#include <vector>
#include <cstdlib>
//#include <bits/stdc++.h>
//#define LOACL
#define space " "
using namespace std;
typedef long long LL;
//typedef __int64 Int;
typedef pair<int, int> paii;
const int INF = 0x3f3f3f3f;
const double ESP = 1e-5;
const double PI = acos(-1.0);
const int MOD = 1e9 + 7;
const int MAXN = 15;
int n, m;
struct Matrix {
    LL m[MAXN][MAXN];
    int row, col;
};
Matrix ori, res;
void init() {
    ori.m[2][4] = ori.m[3][3] = ori.m[3][4] = ori.m[4][4] = 1;
    ori.m[1][1] = ori.m[1][2] = ori.m[1][3] = ori.m[2][2] = 1;
    ori.m[1][4] = ori.m[2][1] = ori.m[3][1] = 0; ori.m[2][3] = 2;
    ori.m[3][2] = ori.m[4][1] = ori.m[4][2] = ori.m[4][3] = 0;
    ori.col = ori.row = 4;
}
Matrix multi(Matrix x, Matrix y) {
    Matrix z;
    memset(z.m, 0, sizeof(z.m));
    z.row = x.row; z.col = y.col;
    for (int i = 1; i <= x.row; i++) {
        for (int k = 1; k <= x.col; k++) {
            for (int j = 1; j <= y.col; j++) {
                z.m[i][j] += x.m[i][k]*y.m[k][j]%MOD;
            }
            z.m[i][k] %= MOD;
        }
    }
    return z;
}
Matrix pow_mod(Matrix a, LL x){
    Matrix b;
    b.col = a.col; b.row = a.row;
    memset(b.m, 0, sizeof(b.m));
    for (int i = 1; i <= 4; i++) {
        b.m[i][i] = 1;
    }
    while(x){
        if(x&1) b = multi(a,b);
        a = multi(a, a);
        x >>= 1;
    }
    return b;
}
int main() {
    int T;
    init();
    LL f, n;
    scanf("%d", &T);
    while (T--) {
        scanf("%lld%lld", &f, &n);
        res = pow_mod(ori, n - 1);
        LL ans = (f*res.m[1][1]%MOD + 4*res.m[1][2]%MOD + 2*res.m[1][3]%MOD + res.m[1][4]%MOD)%MOD;
        printf("%lld\n", ans);
    }
    return 0;
}

 


  

 

posted @ 2016-11-02 19:40  zprhhs  阅读(177)  评论(0编辑  收藏  举报
Power by awescnb