233 Matrix HDU - 5015 (矩阵快速幂)
In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 23333, or 233333 … in the same meaning. And here is the question: Suppose we have a matrix called 233 matrix. In the first line, it would be 233, 2333, 23333… (it means a 0,1 = 233,a 0,2 = 2333,a 0,3 = 23333…) Besides, in 233 matrix, we got a i,j = a i-1,j +a i,j-1( i,j ≠ 0). Now you have known a 1,0,a 2,0,…,a n,0, could you tell me a n,m in the 233 matrix?
Input
There are multiple test cases. Please process till EOF.
For each case, the first line contains two postive integers n,m(n ≤ 10,m ≤ 10 9). The second line contains n integers, a 1,0,a 2,0,…,a n,0(0 ≤ a i,0 < 2 31).
Output
For each case, output a n,m mod 10000007.
Sample Input
1 1
1
2 2
0 0
3 7
23 47 16
Sample Output
234
2799
72937
题意:给出一个矩阵(假设为a)的第一列的1~n个元素,求a[n][m]。
该矩阵满足以下条件:
1.对于第一行:
a[0][1]=233,a[0][2]=2333,a[0][3]=23333……(也就是a[0][i]=a[0][i-1]*10+3)
2.对于其他元素,满足a[i][j]=a[i-1][j]+a[i][j-1]
思路:
这个题是关于矩阵的,而以我目前所接触的算法只有矩阵快速幂,所以马上就想到了构造矩阵。通常矩阵快速幂的题是通过一列数乘上一个构造矩阵来推出另一列数。对于这个题,从第一列开始推到第二列。
第一列为:
23
a[1][0]
a[2][0]
a[3][0]
.
.
.
a[n][0]
3
因为第一行的数满足a[0][i]=a[0][i-1]*10+3,所以每一列的最后一个数要是3。根据矩阵乘法(左边的矩阵列数等于右边的矩阵行数),构造矩阵的的列数为n+2。
第二列为:
233
a[1][0]+a[0][1] (233)
a[2][0]+a[1][1] (a[1][0]+233)
a[3][0]+a[2][1] (a[2][0]+a[1][0]+233)
.
.
.
a[n][0]+a[n-1][1] (a[n-1][0]+a[n-2][0]+233)
3
现在根据第一列,第二列的关系来构造矩阵。
对于第二列的第i(i>=2)个元素:
1.要加上233,所以构造矩阵的每一行的第一个元素是10,最后一个元素是1。
2.要加上其第一列的前 i-1个元素。
3.每一列的最后一个元素为3。
所以,构造出的矩阵为:
10 0 0 0 ……1
10 1 0 0 ……1
10 1 1 0 ……1
10 1 1 1 ……1
0 0 0 0 ……1
对于构造的矩阵,其1次方可求出a[n][1],所以m次方才可求出a[n][m]。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const int mod=1e7+7;
int n;
struct mat
{
LL m[15][15];
mat() //构造函数,是每个矩阵初始化为0
{
int i,j;
for(i=0;i<15;i++)
for(j=0;j<15;j++)
m[i][j]=0;
}
};
mat mul(mat a,mat b)
{
mat c;
int i,j,k;
for(i=0;i<n+2;i++)
for(j=0;j<n+2;j++)
for(k=0;k<n+2;k++)
c.m[i][j]=(c.m[i][j]+(a.m[i][k]*b.m[k][j])%mod)%mod;
return c;
}
mat q_pow(mat a,LL b)
{
mat ans;
int i;
for(i=0;i<15;i++)
ans.m[i][i]=1;
while(b)
{
if(b&1)
ans=mul(ans,a);
a=mul(a,a);
b/=2;
}
return ans;
}
int main()
{
LL m;
while(cin>>n>>m)
{
LL arr[15]; //储存第一列的数
arr[0]=23;
LL i,j;
for(i=1;i<=n;i++)
scanf("%lld",&arr[i]);
arr[n+1]=3;
mat a; //构造的矩阵
for(i=0;i<n+1;i++)
a.m[i][0]=10;
for(i=0;i<n+2;i++)
a.m[i][n+1]=1;
for(i=1;i<n+1;i++)
for(j=1;j<=i;j++)
a.m[i][j]=1;
mat ans=q_pow(a,m);
int sum=0;
for(i=0;i<n+2;i++)
sum=(sum+(ans.m[n][i]*arr[i])%mod)%mod;
cout<<sum%mod<<endl;
}
return 0;
}
仅仅做了几个矩阵快速幂的题还没有完全熟悉,只能按照自己目前的理解写,觉得不好的轻喷。