题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5015
题意:给出a1,0 a2,0 a3,0...an,0 ,而且(a0,1 = 233,a0,2 = 2333,a0,3 = 23333...),以及ai,j = ai-1,j +ai,j-1( i,j ≠ 0),求an,m(n ≤ 10,m ≤ 109)。
思路:看到m那么大 反而n却不大,可以想到利用矩阵转移,快速幂加速计算。
我们按照列来转移,我们知道a1,0 a2,0 a3,0 ... 转移一次后可以得到a1,1 a2,1 a3,1....。
a1,1 = a1,0 + a0,1
a2,1 = a2,0 + a1,1 = a2,0 + a1,0 + a0,1
a3,1 = a3,0 + a2,1 = a3,0 + a2,0 + a1,1 = a3,0 + a2,0 + a1,0 + a0,1
依次类推,第i列转移到第i+1列的时候,aj,i+1 = a0,i+1 + ∑ak,i (1<=k<=j)
现在我们再考虑怎么去转移每一列的233,a0,i+1 = 10 * a0,i + 3。
所以我们构造一个12*12的转移矩阵 (x1,x2...,x10,233,3)*
前1~10列是转移x1~x10,第11列是转移233,第12列是继续记录3
1 1 1 1 1 1 1 1 1 1 0 0
0 1 1 1 1 1 1 1 1 1 0 0
0 0 1 1 1 1 1 1 1 1 0 0
0 0 0 1 1 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 1 0 0
0 0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 1 1 1 1 0 0
0 0 0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 0 0 0 1 0 0
1 1 1 1 1 1 1 1 1 1 10 0
0 0 0 0 0 0 0 0 0 0 1 1
<span style="font-size:18px;">#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod 10000007
struct matrix
{
LL a[12][12];
void E()
{
rep(i,0,11)
rep(j,0,11)
if ( i == j )
a[i][j] = 1;
else
a[i][j] = 0;
}
void init()
{
rep(i,0,11)
rep(j,0,11) a[i][j] = 0;
}
void zhuanyi()
{
init();
rep(i,0,9)
rep(j,0,i)
a[j][i] = 1;
rep(i,0,9) a[10][i] = 1;
a[10][10] = 10;
a[11][10] = 1;
a[11][11] = 1;
}
};
int m,n;
int x[15];
matrix multi( matrix & tx , matrix & ty )
{
matrix ans;
ans.init();
rep(i,0,11)
rep(j,0,11)
rep(k,0,11)
ans.a[i][j] = ( ( ans.a[i][j] + tx.a[i][k] * ty.a[k][j] ) % mod + mod ) % mod;
return ans;
}
int solve()
{
if ( m == 0 ) return ( x[n-1] % mod + mod ) % mod;
matrix ans,temp;
temp.zhuanyi();
ans.E();
while( m )
{
if ( m & 1 ) ans = multi( ans , temp );
temp = multi( temp , temp );
m >>= 1;
}
LL t = 0;
x[10] = 233;
x[11] = 3;
rep(i,0,11) t = ( ( t + (x[i] * ans.a[i][n-1] % mod) ) % mod + mod ) % mod;
return t;
}
int main()
{
while( scanf("%d%d",&n,&m) == 2 )
{
Clean(x,0);
rep(i,0,n-1) scanf("%d",&x[i]);
cout<<solve()<<endl;
}
return 0;
}</span>