LuoGu: CF392C Yet Another Number Sequence
CF: C. Yet Another Number Sequence
如果一般的斐波那契数列前缀和可以直接矩阵加速。考虑增加了 $i ^ k$ 如何实现。
$$ \begin {aligned} & F _ {i + 1} (i + 1) ^ k \\ = & (F _ {i - 1} + F _ i) (i + 1) ^ k \\ = & F _ {i - 1} ((i - 1) + 2) ^ k + F _ i (i + 1) ^ k \\ = & \sum _ {j = 0} ^ k \binom k j 2 ^ {k - j} F _ {i - 1} (i - 1) ^ j + \sum _ {j = 0} ^ k \binom k j F _ i i ^ j \end {aligned} $$
这样,维护 $F _ i, F _ {i - 1}$ 和 $i ^ 0, i ^ 1, \ldots , i ^ k$ 乘积即可转移。
查看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 #include <cstdio> using namespace std;template <class Type >void read (Type &x) { char c; bool flag = false ; while ((c = getchar ()) < '0' || c > '9' ) c == '-' && (flag = true ); x = c - '0' ; while ((c = getchar ()) >= '0' && c <= '9' ) x = (x << 3 ) + (x << 1 ) + c - '0' ; if (flag) x = ~x + 1 ; } template <class Type , class ...rest >void read (Type &x, rest &...y) { read (x), read (y...); }template <class Type >void write (Type x) { if (x < 0 ) putchar ('-' ), x = ~x + 1 ; if (x > 9 ) write (x / 10 ); putchar (x % 10 + '0' ); } typedef long long LL;const int N = 90 , mod = 1e9 + 7 ;struct Matrix { int n, m, w[N][N]; Matrix (int _n, int _m) { n = _n, m = _m; } void clear () { for (int i = 0 ; i < n; ++i) for (int j = 0 ; j < m; ++j) w[i][j] = 0 ; } void init () { for (int i = 0 ; i < n; ++i) for (int j = 0 ; j < m; ++j) w[i][j] = i == j; } Matrix operator * (Matrix _) const { Matrix res (n, _.m) ; res.clear (); for (int i = 0 ; i < n; ++i) for (int j = 0 ; j < _.m; ++j) for (int k = 0 ; k < m; ++k) res.w[i][j] = (res.w[i][j] + (LL)w[i][k] * _.w[k][j]) % mod; return res; } }; LL n; int m, p[N], C[N][N];void init () { p[0 ] = 1 ; for (int i = 1 ; i <= m; ++i) p[i] = p[i - 1 ] * 2 % mod; for (int i = 0 ; i <= m; ++i) C[i][0 ] = 1 ; for (int i = 1 ; i <= m; ++i) for (int j = 1 ; j <= m; ++j) C[i][j] = (C[i - 1 ][j - 1 ] + C[i - 1 ][j]) % mod; } Matrix binpow (Matrix b, LL k) { Matrix res (b.n, b.m) ; res.init (); for (; k; k >>= 1 , b = b * b) if (k & 1 ) res = res * b; return res; } int main () { read (n, m); init (); static Matrix A (1 , 2 * m + 3 ) , B (2 * m + 3 , 2 * m + 3 ) ; A.clear (), B.clear (); B.w[2 * m + 1 ][2 * m + 2 ] = B.w[2 * m + 2 ][2 * m + 2 ] = 1 ; for (int i = 0 ; i <= m; ++i) { B.w[i + m + 1 ][i] = 1 ; for (int j = 0 ; j <= i; ++j) { B.w[j + m + 1 ][i + m + 1 ] = C[i][j]; B.w[j][i + m + 1 ] = (LL)C[i][j] * p[i - j] % mod; } } A.w[0 ][2 * m + 2 ] = 1 ; for (int i = 0 ; i <= m; ++i) { A.w[0 ][i] = 1 ; A.w[0 ][i + m + 1 ] = p[i] * 2 % mod; } write (((A * binpow (B, n - 1 )).w[0 ][2 * m + 2 ] + mod) % mod); return 0 ; }