题意:
给定矩阵的第一行和第一列,其余每项 a [ i ] [ j ] = a [ i − 1 ] [ j ] + a [ i ] [ j − 1 ] a[i][j] = a[i-1][j] + a[i][j-1] a[i][j]=a[i−1][j]+a[i][j−1],求 a n , m % 10000007 a_{n,m}\% 10000007 an,m%10000007
数据范围:
n < = 10 , m < = 1 0 9 , 0 < = a 1 , 0 , a 2 , 0 , . . . , a n , o < 2 31 n<=10,m<=10^9,0<=a_{1,0},a_{2,0},...,a_{n,o}<2^{31} n<=10,m<=109,0<=a1,0,a2,0,...,an,o<231
思路:
首先第0行为0, 233, 23333...
,为了使递推式
a
0
,
j
=
10
∗
a
0
,
j
−
1
+
3
a_{0,j}=10*a_{0,j-1}+3
a0,j=10∗a0,j−1+3成立,把第一个0变为23,即
a
0
,
0
a_{0,0}
a0,0视作23。
- 第 0 行, a 0 , j = 10 a 0 , j − 1 + 3 a_{0,j}=10a_{0,j-1}+3 a0,j=10a0,j−1+3
- 第 1 行, a 1 , j = a 1 , j − 1 + a 0 , j = a 1 , j − 1 + 10 a 0 , j − 1 + 3 a_{1,j}=a_{1,j-1}+a_{0,j}=a_{1,j-1}+10a_{0,j-1}+3 a1,j=a1,j−1+a0,j=a1,j−1+10a0,j−1+3
- 第 2 行, a 2 , j = a 2 , j − 1 + a 1 , j = a 2 , j − 1 + a 1 , j − 1 + 10 a 0 , j − 1 + 3 a_{2,j}=a_{2,j-1}+a_{1,j}=a_{2,j-1}+a_{1,j-1}+10a_{0,j-1}+3 a2,j=a2,j−1+a1,j=a2,j−1+a1,j−1+10a0,j−1+3
- … …
- 第 n 行,
a
n
,
j
=
∑
i
=
1
n
a
i
,
j
−
1
+
10
a
0
,
j
−
1
+
3
a_{n,j}=\sum_{i=1}^{n}a_{i,j-1}+10a_{0,j-1}+3
an,j=∑i=1nai,j−1+10a0,j−1+3
重点是怎么构造矩阵呢?
线代知识,把等式左边构成一列向量,等式右边的系数就是系数矩阵(也就是所要求的构造矩阵)。当时在求大数fibonacci项时, f n = f n − 1 + f n − 2 f_n=f_n{-1}+f_{n-2} fn=fn−1+fn−2只需构造一个2*2矩阵即可。而这里最后存在非线性项+3,要给左边的列向量,n + 1 行增广一个常数 1,共 n + 2 行,
将上面的递推写成矩阵形式
可以看出后一列可由前一列递推得来。要求
a
n
,
m
a_{n,m}
an,m,也就是第 m 列的情况,递推得:
矩阵的 m 次幂可用矩阵快速幂解决。
最后
a
n
,
m
=
∑
j
=
0
n
+
1
a
n
s
[
n
]
[
j
]
∗
c
o
l
[
j
]
a_{n,m}=\sum_{j=0}^{n+1}ans[n][j] * col[j]
an,m=∑j=0n+1ans[n][j]∗col[j]
input:
1 1
1
2 2
0 0
3 7
23 47 16
output:
234
2799
72937
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=12; //矩阵最多 12 阶
const int MOD=10000007;
int col[maxn]; //矩阵第一列
int n,m;
struct matrix{
ll a[maxn][maxn];
void init()
{
memset(a,0,sizeof a);
for(int i = 0; i < n + 2; i++)
a[i][i] = 1;
}
};
matrix mul(matrix p, matrix q)
{
matrix ans;
for(int i = 0; i < n + 2; i++)
{
for(int j = 0; j < n + 2; j++)
{
ans.a[i][j] = 0;
for(int k = 0; k < n + 2; k++)
ans.a[i][j] = (ans.a[i][j] + p.a[i][k] * q.a[k][j])%MOD;
}
}
return ans;
}
matrix qpow(matrix tag, int k) //矩阵快速幂
{
matrix ans;
ans.init();
while(k)
{
if(k&1)
ans = mul(ans, tag);
tag = mul(tag, tag);
k>>=1;
}
return ans;
}
int main()
{
while(cin>>n>>m)
{
col[0]=23; //输入第一列
for(int i = 1; i <= n; i++)
cin>>col[i];
col[n+1]=1;
matrix ans; //开始构造矩阵
ans.init();
for(int i = 0; i <= n; i++) //纸上写好,往里填就可以
{
ans.a[i][0]=10;
for(int j = 1; j <= i; j++)
ans.a[i][j] = 1;
ans.a[i][n+1] = 3;
ans.a[n+1][i] = 0;
}
ans.a[n+1][n+1] = 1;
ans = qpow(ans,m); //ans的 m 次幂
ll res = 0;
for(int j = 0; j < n + 2; j++) //第 n 行累加求和
res = (res + ans.a[n][j] * col[j])%MOD;
cout<<res<<endl;
}
return 0;
}