题意:
给定一个n行m列的矩阵, 长成这样
从第一行第一列开始 a[i][j] = a[i-1][j-1] + a[i-1][j];
然后求 a[n][m];
思路:
很明显, 设第i列的列向量为
m有点大, 同时n<=10, 可以考虑用矩阵快速幂加速, 但是递推的向量只有n维明显不是很行, 所以加两维, 变成
设上面中间的矩阵为A, 则 f[i] = A * f[i-1], f[m] = A ^ ( m - 1 ) * f[1];
先求出 f[1], 再用矩阵快速幂求出 f[m]
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define mxn 100020
#define mod 10000007
#define LL long long
int n, m;
int b[15][15];
void get_b() {
memset( b, 0, sizeof( b ) );
b[0][0] = 1;
b[1][0] = 3, b[1][1] = 10;
for( int i = 2; i <= n + 1; ++i ) {
for( int j = 0; j <= n + 1; ++j )
b[i][j] = b[i-1][j];
b[i][i] = 1;
}
}
struct mat {
LL a[15][15];
mat() {
memset( a, 0, sizeof( a ) );
}
mat( int x ) {
for( int i = 0; i <= n + 1; ++i )
for( int j = 0; j <= n + 1; ++j )
a[i][j] = b[i][j];
}
mat( int x, int y ) {
memset( a, 0, sizeof( a ) );
for( int i = 0; i <= n + 1; ++i )
a[i][i] = 1;
}
mat operator * ( const mat& b ) const {
mat ret;
for( int i = 0; i <= n + 1; ++i )
for( int j = 0; j <= n + 1; ++j )
for( int k = 0; k <= n + 1; ++k )
ret.a[i][j] = ( ret.a[i][j] + a[i][k] * b.a[k][j] ) % mod;
return ret;
}
};
mat qpow( mat t, int k ) {
mat ret( 1, 1 );
while( k ) {
if( k & 1 )
ret = ret * t;
t = t * t;
k >>= 1;
}
return ret;
}
LL a[30], c[30];
int main() {
while( scanf( "%d%d", &n, &m ) != EOF ) {
for( int i = 1; i <= n; ++i )
scanf( "%d", &a[i] );
get_b();
mat t( 1 );
t = qpow( t, m - 1 );
c[0] = 1;
c[1] = 233;
for( int i = 2; i <= n + 1; ++i )
c[i] = ( c[i-1] + a[i-1] ) % mod;
LL ans = 0;
for( int i = 0; i <= n + 1; ++i )
ans = ( ans + c[i] * t.a[n+1][i] ) % mod;
printf( "%I64d\n", ans );
}
return 0;
}