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)。
如下图:

HDU 5012 233 Matrix
图片橙色部分等于蓝色部分的和,也就是上边的公式。
我们的目的是由当前蓝色的部分,推出与它紧邻的右边下一列蓝色的部分。
构造如下矩阵,我们希望找出一个n+1阶的方阵,使得如下矩阵式成立。

HDU 5012 233 Matrix

根据上述推导的公式,可得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。则矩阵就变成:

HDU 5012 233 Matrix

相应的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的形式如下:

HDU 5012 233 Matrix

由于矩阵乘法的结合律,可得:

HDU 5012 233 Matrix

这样就可以对矩阵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;
}

 

相关文章:

  • 2021-09-05
  • 2021-07-11
  • 2021-12-24
  • 2022-01-19
  • 2022-03-03
  • 2021-05-29
  • 2022-02-01
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-10-20
  • 2021-11-05
  • 2021-12-05
  • 2021-11-17
  • 2021-12-30
  • 2022-12-23
相关资源
相似解决方案