[洛谷P1939]模板矩阵加速(数列)

Posted Mrsrz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[洛谷P1939]模板矩阵加速(数列)相关的知识,希望对你有一定的参考价值。

题目大意:给你一个数列a,规定$a[1]=a[2]=a[3]=1$,$a[i]=a[i-1]+a[i-3](i>3)$求$a[n]\ mod\ 10^9+7$的值。

解题思路:这题看似是很简单的递推,但是$n\leq 2×10^9$,递推肯定是会超时的。故我们需要优化。

常见优化有矩阵加速,还有什么我并不知道了。

用矩阵可将此类题目时间复杂度从$O(n)$优化为$O(\log_2 n)$。

具体对于此类形如$f(n)=f(n-1)*p(1)+f(n-2)*p(2)+...+f(n-k)*p(k)$的线性递推问题,有如下解法。

设$F[i]=\begin{bmatrix} F[n-k] \\F[n-k+1]\\F[n-k+2]\\...\\F[2]\\F[1] \end{bmatrix}\quad$,

则$F[n]=F[n-1]*\begin{bmatrix} 0&1&0&0&...&0\\0&0&1&0&...&0\\0&0&0&1&...&0\\...&...&...&...&...&...\\0&0&0&0&...&1\\p[k]&p[k-1]&p[k-2]&p[k-3]&...&p[1]\end{bmatrix}\quad$。

运用矩阵快速幂即可完成加速。

故此题解法如下。

$$\begin{bmatrix}F[n-2]\\F[n-1]\\F[n]\end{bmatrix}\quad =\begin{bmatrix}0&1&0\\0&0&1\\1&0&1\end{bmatrix}^{n-1}\quad×\begin{bmatrix}F[1]\\F[2]\\F[3]\end{bmatrix}\quad$$

C++ Code:

#include<cstdio>
#include<cstring>
using namespace std;
struct mat{
	long long a[30][30];
	int r,c;
};
mat mul(mat x,mat y){
	mat ans;
	memset(&ans,0,sizeof ans);
	for(int i=0;i<x.r;++i)
	for(int j=0;j<y.c;++j)
	for(int k=0;k<x.c;++k)
	ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j])%1000000007;
	ans.r=x.r;
	ans.c=y.c;
	return ans;
}
void pow(int n){
	mat p;
	memset(&p,0,sizeof p);
	p.r=p.c=3;
	p.a[0][1]=p.a[1][2]=p.a[2][0]=p.a[2][2]=1;
	mat ans;
	memset(&ans,0,sizeof ans);
	ans.r=ans.c=3;
	ans.a[0][0]=ans.a[1][1]=ans.a[2][2]=1;
	while(n){
		if(n&1){
			ans=mul(ans,p);
		}
		p=mul(p,p);
		n>>=1;
	}
	p.a[0][0]=p.a[0][1]=p.a[0][2]=1;
	p.c=1;
	mul(ans,p);
	printf("%d\n",(int)ans.a[2][2]);
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		if(n<4)puts("1");else
		pow(n-1);
	}
	return 0;
}

 

以上是关于[洛谷P1939]模板矩阵加速(数列)的主要内容,如果未能解决你的问题,请参考以下文章

P1939模板矩阵加速(数列)

P1939 模板矩阵加速(数列)

P1939 模板矩阵加速(数列)

P1939 模板矩阵加速(数列)

luogu P1939 模板矩阵加速(数列) 题解

[LGOJ]P1939模板矩阵加速(数列)[矩阵加速递推]