递推【矩阵乘法】

D e s c r i p t i o n Description Description

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

I n p u t Input Input

第一行两个整数:n,k。其中n表示这是一个N阶线性递推式,k表示你需要球的那一项。
第二行有n+1个整数:a0,a1,…an,表示这个递推式的系数。
第三行有n个整数:f0,f1,…,fn-1表示数列的初始值。

O u t p u t Output Output

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

S a m p l e Sample Sample I n p u t Input Input
2 10
1 1 0
0 1
S a m p l e Sample Sample O u t p u t Output Output
55

H i n t Hint Hint

对于50%的数据 k<=10^6
对于100%的数据
1<=k<=10^18
1<=a_i,f_i<=10^4

T r a i n Train Train o f of of T h o u g h t Thought Thought

相当于构造一个(n + 1) * (n + 1)的矩阵

0 0 0 a 1 a_1 a1 0
1 0 0 a 2 a_2 a2 0
0 1 0 a 3 a_3 a3 0
0 0 1 a 4 a_4 a4 0
0 0 0 a n − 1 a_{n-1} an1 0
0 0 0 a n a_n an 0
0 0 0 1 1

嗯然后矩阵乘法

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;

const ll mod = 9973;

ll n, m, l;
ll B[105];

struct wh_
{
    
    
	ll h[105][105];
	ll n; 
}A, K;

wh_ operator *(wh_ a, wh_ b)
{
    
    
	wh_ c;
	memset(c.h, 0, sizeof(c.h));
	for(int i = 1; i <= m; ++i)
		for(int j = 1; j <= m; j++)
			for(int k = 1; k <= m; k++)
				c.h[i][j] = (c.h[i][j] + a.h[i][k] * b.h[k][j] % mod) % mod;
	return c;
}

void power(ll m)
{
    
    
	while(m)
	{
    
    
		if(m & 1)K = K * A;
		A = A * A;
		m >>= 1;
	}
}

int main()
{
    
    
	scanf("%lld%lld", &n, &l);m = n + 1;
	for(int i = 1; i <= m; ++i)
		scanf("%lld", &B[i]);
		
	for(int i = 1; i < n; ++i)
		A.h[i + 1][i] = 1;
		
	for(int i = 1; i <= n; ++i)
		A.h[i][n] = B[i];
	
	A.h[m][m] = A.h[m][n] = 1;  
	for(int i = 1; i <= n; ++i)
		scanf("%lld", &K.h[1][i]);
	K.h[1][m] = B[m];
	
	power(l - n + 1);
	
	printf("%lld", K.h[1][n]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SSL_wujiajie/article/details/111406942