递推

题目描述 

JYM和XJ转眼就从小学上了高中。在学习递推的时候,JYM在纸上随手写了一个递推关系式:an=2*an-1,a0=0。写完这个递推式,JYM拿给XJ看,XJ觉得太过简单,于是大笔一挥,在等式右边又加了一个式子,变成了这样:an=2*an-1+n2。JYM看到这个式子,想要算几个项来看看,可是一算就发现这个数据量太大了,你能帮他解决这个问题吗?

输入描述:

输入数据有多组(不超过100组数据),每组数据包含一个整数N<=1018

输出描述:

一个整数X,表示递推式第n项的值。由于数字太大,因此结果对于1000000009取模后输出。

输入

0
1
2
3

输出

0
1
6
21
// a(n) = 2 * a(n - 1) + n^2
// a(n) = 2 * (2 * a(n - 2) + (n - 1)^2) + n^2
// a(n) = 2^2 * a(n - 2) + 2 * (n - 1)^2 + n^2
// a(n) = 2^n * a(0) + 2^(n - 1) * 1^2 + 2^(n - 2) * 2^2 + ... + 2^1 * (n - 1)^2 + 2^0 * n^2
// 通项2^i * (n - i)^2 for i in range(0, n + 1)
// a(n) = 2 * a(n - 1) + (n - 1)^2 + 2 * (n - 1) + 1
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MOD = 1e9 + 9;
void mulself(LL a[4][4]) {
    LL c[4][4] = {0};
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            for (int k = 0; k < 4; k++) {
                c[i][j] = (c[i][j] + a[i][k] * a[k][j]) % MOD;
            }
        }
    }
    memcpy(a, c, sizeof(c));
} 
void mul(LL a[4][4], LL b[4][4]) {
    LL c[4][4] = {0};
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            for (int k = 0; k < 4; k++) {
                c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % MOD;
            }
        }
    }
    memcpy(a, c, sizeof(c));
}
int main() {
    LL n;
    while (cin >> n) {
        LL ans[4][4] = {0};
        LL a[4][4] = {{2, 1, 2, 1}, {0, 1, 2, 1}, {0, 0, 1, 1}, {0, 0, 0, 1}};
        for (int i = 0; i < 4; i++) ans[i][i] = 1;
        while (n) {
            if (n & 1) mul(ans, a);
            mulself(a);
            n >>= 1;
        }
        cout << ans[0][3] << endl;
    }
    return 0;
}
posted @ 2020-07-22 15:08  HighLights  阅读(265)  评论(0)    收藏  举报