SSL 1532 递推【矩阵乘法】【快速幂】

题目链接


题意

给出前n项和其系数以及一项常数
f [ n ] = a 0 ∗ f [ i − n ] + a 1 ∗ f [ i − n + 1 ] + … + a n f[n]=a0 * f[i-n] + a1 * f[i-n+1] + … + an f[n]=a0f[in]+a1f[in+1]++an
求这个数列的第k项

思路

考虑 [ f i − n f i − n + 1 f i − n + 2 … … f i − 1 1 ] \begin{bmatrix}f_{i-n} & f_{i-n+1} & f_{i-n+2} & …… f_{i-1} & 1\end{bmatrix} [finfin+1fin+2fi11]转换到
[ f i − n + 1 f i − n + 2 f i − n + 3 … … f i 1 ] \begin{bmatrix}f_{i-n+1} & f_{i-n+2} & f_{i-n+3} & …… f_{i} & 1\end{bmatrix} [fin+1fin+2fin+3fi1]
于是转移矩阵就是
[ 0 0 … … a 1 0 1 0 … … a 2 0 0 1 … … a 3 0 … 0 0 … … a n + 1 1 ] \begin{bmatrix}0 & 0 & …… & a_1 & 0\\1 & 0 & …… & a_2 & 0\\0 & 1 & …… & a_3 & 0\\…\\0 & 0 & …… & a_{n+1} & 1\end{bmatrix} 01000010a1a2a3an+10001

代码

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const long long mod=9973;
long long a[2020][2021],ans[2020][2021],b[2][202021];
long long n,k;
void jzcf(long long m)
{
    
    
	int c[202][202];
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    c[i][j]=0;
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	  for(int k=1; k<=m; k++)
	     c[i][j]=(c[i][j]+(a[i][k]*ans[k][j])%mod)%mod;
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    ans[i][j]=c[i][j];
}
void jzcf1(long long m)
{
    
    
	int c[202][202];
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    c[i][j]=0;
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	  for(int k=1; k<=m; k++)
	     c[i][j]=(c[i][j]+(a[i][k]*a[k][j])%mod)%mod;
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    a[i][j]=c[i][j];
}
void jzcf2(long long m)
{
    
    
	int c[200][202];
	for(int i=1; i<=m; i++)
	 for(int j=1; j<=m; j++)
	    c[i][j]=0;
	for(int i=1; i<=1; i++)
	 for(int j=1; j<=m; j++)
	  for(int k=1; k<=m; k++)
	     c[i][j]=(c[i][j]+(b[i][k]*ans[k][j])%mod)%mod;
	for(int i=1; i<=1; i++)
	 for(int j=1; j<=m; j++)
	    b[i][j]=c[i][j];
}
void ksm(long long x)
{
    
    
	for(int i=1; i<=n+1; i++)
	   ans[i][i]=1;
	while(x!=0)
	 {
    
    
	 	if(x&1)
	 	  jzcf(n+1);
	 	jzcf1(n+1);
	 	x>>=1;
	 }
}
int main()
{
    
    
	cin>>n>>k;
	for(int i=1; i<=n+1; i++)
	   scanf("%lld",&a[i][n]);
	for(int i=1; i<=n; i++)
	   scanf("%lld",&b[1][i]);
	b[1][n+1]=1;
	for(int i=1; i<=n-1; i++)
	   a[i+1][i]=1;
	a[n+1][n+1]=1;
	ksm(k);
	jzcf2(n+1);
	cout<<b[1][1];
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jackma_mayichao/article/details/111402168