Problem Description
Lele now is thinking about a simple function f(x).
If x < 10 f(x) = x.
If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10);
And ai(0<=i<=9) can only be 0 or 1 .
Now, I will give a0 ~ a9 and two positive integers k and m ,and could you help Lele to caculate f(k)%m.
Input
The problem contains mutiple test cases.Please process to the end of file.
In each case, there will be two lines.
In the first line , there are two positive integers k and m. ( k<2*10^9 , m < 10^5 )
In the second line , there are ten integers represent a0 ~ a9.
Output
For each case, output f(k) % m in one line.
Sample Input
10 9999
1 1 1 1 1 1 1 1 1 1
20 500
1 0 1 0 1 0 1 0 1 0
Sample Output
45
104
题目大意
一个线性递推的式子,求第k项是多少。
思路
k最大是2*10^9,如果用int存,数组会爆,时间可能也会超。
可以将递推公式写成矩阵相乘的形式,由于矩阵相乘有结合性,中间项a0-a9都是常数,如果可以把它变成n*n的矩阵,就可以自乘,然后用快速幂将时间复杂度降为logn。
将第三个10*1的向量展开,得到
这样将中间的矩阵转化为n*n的矩阵,就可以自乘,可以用快速幂。
矩阵快速幂求解递推式的第n项问题。想到矩阵快速幂,然后要构造矩阵,两个向量是差1,中间的方阵要配系数配出来。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 10;
int k,mod;
int arr[N];
struct Matrix
{
ll m[N][N];
friend Matrix operator*(const Matrix& a,const Matrix& b)
{
Matrix t;
memset(t.m,0,sizeof(t.m));
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
int sum = 0;
for(int k=0;k<N;k++){
sum += (a.m[i][k]%mod)*(b.m[k][j]%mod)%mod;
t.m[i][j] = sum%mod;
}
}
}
return t;
}
};
Matrix qpow(Matrix a,int k)
{
Matrix ans;
memset(ans.m,0,sizeof(ans.m));
for(int i=0; i<N;i++)
ans.m[i][i] = 1;
while(k)
{
if(k&1) ans = ans*a;
a = a*a;
k>>=1;
}
return ans;
}
void init(Matrix &a) {
memset(a.m, 0, sizeof(a.m));
for (int i = 0; i < N; i++)
{
a.m[0][i] = arr[i];
if(i<N-1) a.m[i + 1][i] = 1;
}
}
int main()
{
Matrix x,y;
while(~scanf("%d %d",&k,&mod))
{
for(int i=0;i<N;i++)
scanf("%d",&arr[i]);
init(x);
memset(y.m,0,sizeof(y.m));
for(int i=0;i<N;i++){
y.m[i][0] = N-1-i;
}
k -= 9;
x = qpow(x,k)*y;
printf("%lld\n", x.m[0][0]);
}
return 0;
}