P5364 SNOI2017 礼物 - 洛谷 (luogu.com.cn)
0.分析
毫无疑问的数学题,设 :第
个朋友带来的礼物数,
。
有
。
对于
,
,
。
求 。
不难发现转移式子是固定的,可以往矩阵乘法加速 dp 的方向想。
对于 ,我们发现这类似二项式定理:
由于 ,只要将
也放到矩阵里,就可以加速了。
1.设计


2.代码
cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 14;
const LL P = 1000000007;
LL n; int K;
struct Matrix {
LL a[N][N];
Matrix() {
memset(a, 0, sizeof(a));
}
};
LL C[N][N];
Matrix operator*(Matrix a, Matrix b) {
Matrix c;
for (int i = 0; i <= K + 2; i ++) {
for (int k = 0; k <= K + 2; k ++) {
for (int j = 0; j <= K + 2; j ++) {
c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % P) % P;
}
}
}
return c;
}
Matrix q_pow(Matrix a, LL b) {
Matrix c;
for (int i = 0; i <= K + 2; i ++) {
c.a[i][i] = 1;
}
while (b) {
if (b & 1) {
c = c * a;
}
a = a * a;
b >>= 1;
}
return c;
}
void init() {
memset(C, 0, sizeof(C));
C[0][0] = 1;
for (int i = 0; i <= 13; i ++) {
C[i][0] = C[i][i] = 1;
for (int j = 1; j < i; j ++) {
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % P;
}
}
}
int main () {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> K;
init();
Matrix m, x, res;
for (int i = 0; i <= K + 2; i ++) {
x.a[i][0] = 1;
}
m.a[0][1] = 1;
for (int t = 0; t <= K; t ++) {
m.a[0][2 + t] = C[K][t];
}
m.a[1][1] = 2;
for (int t = 0; t <= K; t ++) {
m.a[1][2 + t] = C[K][t];
}
for (int j = 0; j <= K; j ++) {
for (int t = 0; t <= j; t ++) {
m.a[j + 2][2 + t] = C[j][t];
}
}
res = q_pow(m, n - 1) * x;
cout << res.a[0][0] << "\n";
return 0;
}