【SSL 1532】递推【矩阵乘法】

Time Limit:10000MS Memory Limit:65536K
Total Submit:71 Accepted:23
Case Time Limit:1000MS


Description

动态规划的实现形式之一是递推,因此递推在 o i oi oi中十分重要。在某信息学的分支学科中,LC学会了如何求一阶线性递推数列。由于他现在正在学习主干学科,因此希望知道求出 N N N阶线性递推数列。为此,他了解到以下内容:
一个N阶线性递推式是这样的式子:
  F 1 = a 0 ∗ F i − n + a 1 ∗ F i − ( n − 1 ) + . . . + a n − 1 ∗ F i − 1 + a n F1=a_0*F_{i-n}+a1*F_{i-(n-1)}+...+a_{n-1}*F_{i-1}+a_n F1=a0Fin+a1Fi(n1)+...+an1Fi1+an
  也就是说,这个数列的每一项都是由他之前的连续N项加权相加所得。其中还包括一个常数 a n an an
  例如,当 N = 2 , a 0 = a 1 = 1 , a 2 = 0 N=2,a0=a1=1,a2=0 N=2a0=a1=1a2=0时,这个式子就是我们熟悉的斐波那契数列。当然,作为边界条件。 f 0 , f 1 , . . . f n − 1 f0,f1,...fn-1 f0f1...fn1都是已知的。
  Lc对如何去求这个式子一筹莫展,因此他想请你帮忙。你的任务是对于一个给定的N阶线性递推式,求出他的第k项。


Input

第一行两个整数: n , k n,k nk。其中n表示这是一个N阶线性递推式,k表示你需要球的那一项。
第二行有 n + 1 n+1 n+1个整数: a 0 , a 1 , . . . . a n a_0,a_1,....a_n a0,a1,....an,表示这个递推式的系数。
第三行有n个整数: f 0 , f 1 , . . . . , f n − 1 f_0,f_1,....,f_n-1 f0,f1,....,fn1表示数列的初始值。

Output

只有一行,其中只有一个整数,表示这个数列第k项的值。由于数据较大,你只需输出 m o d mod mod 9973 9973 9973的值。


Sample Input

2 10
1 1 0
0 1

Sample Output

55


Hint

对于 50 50 50%的数据 n < = k < = 1 0 6 n<=k<=10^6 n<=k<=106
对于 100 100 100%的数据
1 < = n < = k < = 1 0 1 8 1<=n<=k<=10^18 1<=n<=k<=1018
1 < = a i , f i < = 1 0 4 1<=ai,fi<=10^4 1<=ai,fi<=104


解题思路

矩阵乘法呀

F 1 = a 0 ∗ F i − n + a 1 ∗ F i − ( n − 1 ) + . . . + a n − 1 ∗ F i − 1 + a n F1=a_0*F_{i-n}+a1*F_{i-(n-1)}+...+a_{n-1}*F_{i-1}+a_n F1=a0Fin+a1Fi(n1)+...+an1Fi1+an
由题意,我们构造 1 ∗ ( n + 1 ) 1 ∗ ( n + 1 ) 和 ( n + 1 ) ∗ ( n + 1 ) 1 *(n+1)1∗(n+1) 和 (n+1)∗(n+1) 1(n+1)1(n+1)(n+1)(n+1) 的两个矩阵

按照之前的构造思路
第一个矩阵设为 [ f 1 f 2 . . . f n 1 ] \begin{bmatrix} f1&f2&...&fn&1\\ \end{bmatrix} [f1f2...fn1]

f 1 → f 2 f_1→f_2 f1f2 ,可以推出第二个矩阵为 [ 0 0 . . . 0 a 0 0 1 0 . . . 0 a 1 0 0 1 . . . 0 a 2 0 . . . . . . 0 0 . . . 1 a n − 1 0 0 0 . . . 0 a n 1 ] \begin{bmatrix} &0&0&...&0&a_0&0\\ &1&0&...&0&a_1&0\\ &0&1&...&0&a_2&0\\ &&&...&&&&\\ &&&...&&&&\\ &0&0&...&1&a_{n-1}&0\\ &0&0&...&0&a_n&1\\ \end{bmatrix} 0100000100.....................00010a0a1a2an1an00001

因为中间的项转移到下一个矩阵,需要全部向前移一位


代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const long long INF=9973;
long long n,k;
struct c{
    
    
	long long n,m;
	long long a[20][20];
}A,B,CC; 

c operator *(c A,c B){
    
    
	c C;
	C.n=A.n,C.m=B.m;
	for(int i=1;i<=C.n;i++)
		for(int j=1;j<=C.m;j++)
			C.a[i][j]=0;
	for(int k=1;k<=A.m;k++)
		for(int i=1;i<=C.n;i++)
			for(int j=1;j<=C.m;j++)
				C.a[i][j]=(C.a[i][j]+(A.a[i][k]*B.a[k][j]%INF))%INF;
	return C;
}
void poww(long long x){
    
    
	if(x==1)
	{
    
    
		B=A;
		return ;
	}
	poww(x/2);
	B=B*B;
	if(x&1)
		B=B*A;
}
int main(){
    
    
	scanf("%lld%lld",&n,&k);
	A.n=n+1,A.m=n+1;
	CC.n=1,CC.m=n+1;
	for(int i=1;i<=n+1;i++)
		scanf("%lld",&A.a[i][n]);
	for(int i=1;i<=n;i++)
		scanf("%lld",&CC.a[1][i]);
	CC.a[1][n+1]=1;
	for(int i=1;i<=n-1;i++)
		A.a[i+1][i]=1;
	A.a[n+1][n+1]=1;
	poww(k);
	CC=CC*B;
	printf("%lld",CC.a[1][1]);
} 
/*
2 10
1 1 0
0 1
*/

猜你喜欢

转载自blog.csdn.net/kejin2019/article/details/111400530
SSL