https://www.acwing.com/problem/content/228/
要注意类似这种递推的除了用推公式的办法还可以用矩阵快速幂,说不定还会更快,毕竟组合数没有快速的算法。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 10000007;
struct Matrix {
static const int MAXN = 15;
ll ma[MAXN][MAXN];
Matrix() {
init();
}
void init() {
memset(ma, 0, sizeof(ma));
}
void setE() {
init();
for(int i = 0; i < MAXN; ++i)
ma[i][i] = 1;
}
Matrix operator+(const Matrix &m)const {
Matrix Tmp;
Tmp.init();
for(int i = 0; i < MAXN; ++i) {
for(int j = 0; j < MAXN; ++j)
Tmp.ma[i][j] += (ma[i][j] + m.ma[i][j]) % mod;
}
for(int i = 0; i < MAXN; ++i) {
for(int j = 0; j < MAXN; ++j)
if(Tmp.ma[i][j] >= mod)
Tmp.ma[i][j] %= mod;
}
return Tmp;
}
Matrix operator*(const Matrix &m)const {
Matrix Tmp;
Tmp.init();
for(int k = 0; k < MAXN; ++k) {
for(int i = 0; i < MAXN; ++i) {
register int r = ma[i][k];
for(int j = 0; j < MAXN; ++j)
Tmp.ma[i][j] += (r * m.ma[k][j]) % mod;
}
}
for(int i = 0; i < MAXN; ++i) {
for(int j = 0; j < MAXN; ++j)
if(Tmp.ma[i][j] >= mod)
Tmp.ma[i][j] %= mod;
}
return Tmp;
}
void show(int n) {
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
printf("%2d ", ma[i][j]);
}
puts("");
}
}
};
Matrix qpow(Matrix x, ll n) {
Matrix res;
res.setE();
while(n) {
if(n & 1)
res = res * x;
x = x * x;
n >>= 1;
}
return res;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m;
while(~scanf("%d%d", &n, &m)) {
Matrix F;
F.ma[0][0] = 3;
F.ma[1][0] = 23;
for(int i = 1; i <= n; ++i) {
scanf("%d", &F.ma[i + 1][0]);
}
int k = n + 2;
Matrix A;
A.ma[0][0] = 1;
A.ma[1][0] = 1;
A.ma[1][1] = 10;
for(int i = 1; i <= n; ++i) {
A.ma[i + 1][0] = 1;
A.ma[i + 1][1] = 10;
for(int j = 1; j <= i; ++j)
A.ma[i + 1][j + 1] = 1;
}
//A.show(k);
A = qpow(A, m);
F = A * F;
printf("%d\n", F.ma[n + 1][0]);
}
}