233 Matrix
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 4055 Accepted Submission(s): 2299
Problem Description
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 a0,1 = 233,a0,2 = 2333,a0,3 = 23333...) Besides, in 233 matrix, we got ai,j = ai-1,j +ai,j-1( i,j ≠ 0). Now you have known a1,0,a2,0,...,an,0, could you tell me an,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 ≤ 109). The second line contains n integers, a1,0,a2,0,...,an,0(0 ≤ ai,0 < 231).
Output
For each case, output an,m mod 10000007.
Sample Input
1 1
1
2 2
0 0
3 7
23 47 16
Sample Output
234
2799
72937
对于给定的递推式a(i ,j) = a(i - 1, j) + a(i, j - 1),将它展开则a(i, j) = a(i - 1, j) + a(i, j - 1) = a(i - 2, j) + a(i - 1, j - 1) + a(i, j - 1) = a(i - 3, j) + a(i - 2, j - 1) + a(i - 1, j - 1) + a(i, j - 1) = ...
很快就可以发现规律了得到:a(i, j) = a(1, j - 1) + a(2, j - 1) + ... + a(i, j - 1) + a(0, j)。
如下图:
图片橙色部分等于蓝色部分的和,也就是上边的公式。
我们的目的是由当前蓝色的部分,推出与它紧邻的右边下一列蓝色的部分。
构造如下矩阵,我们希望找出一个n+1阶的方阵,使得如下矩阵式成立。
根据上述推导的公式,可得A矩阵的第一行为[1 0 ... 0 1],第二行为[1 1 0 ... 0 1],第三行为[1 1 1 0 ... 0 1],。。。,第n行为[1 1 1 ... 1 1]。
遗憾的是第n+1行无论怎么取值也无法是矩阵式成立。
因为a(0, m + 1) = a(0,m)* 10 + 3,那么显然n+1行的矩阵不能满足要求,可以将矩阵变成n+2行最后一行为3。则矩阵就变成:
相应的A矩阵第一行为[1 0 ... 0 1 0],第二行为[1 1 0 ... 0 1 0],第三行为[1 1 1 0 ... 0 1 0],。。。,第n行为[1 1 1 ... 1 1 0],第n+1行为[0 0 0 0 .... 0 10 1],
第n+2行为[0 0 0 0 ... 0 0 1]。则矩阵A的形式如下:
由于矩阵乘法的结合律,可得:
这样就可以对矩阵A^m使用矩阵快速幂了。
#include <stdio.h>
#include <string.h>
#define ll long long
const int N = 15;
const int MOD = 10000007;
int n, m;
struct Mat {
ll a[N][N];
Mat() {
memset(a, 0, sizeof(a));
}
Mat operator * (Mat b) {
Mat c;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
c.a[i][j] = (c.a[i][j] + a[i][k] * b.a[k][j]) % MOD;
return c;
}
};
Mat f(Mat b, int m) {
Mat c;
for (int i = 0; i < n; i++)
c.a[i][i] = 1;
while (m) {
if (m & 1)
c = c * b;
b = b * b;
m >>= 1;
}
return c;
}
int main() {
while (scanf("%d%d", &n, &m) == 2) {
Mat A;
A.a[0][0] = 1;
A.a[1][0] = 1;
A.a[1][1] = 10;
n += 2;
for (int i = 2; i < n; i++)
for (int j = 1; j <= i; j++)
A.a[i][j] = 1;
A = f(A, m);
ll temp[N], res = 0;
temp[0] = 3;
temp[1] = 233;
for (int i = 2; i < n; i++)
scanf("%lld", &temp[i]);
for (int i = 0; i < n; i++)
res = (res + temp[i] * A.a[n - 1][i] % MOD) % MOD;
printf("%lld\n", res);
}
return 0;
}