码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-10-05 17:17:27      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:turn   clu   c++   begin   矩阵加速   void   while   div   cstring   

题目大意:给你一个数列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]【模板】矩阵加速(数列)

标签:turn   clu   c++   begin   矩阵加速   void   while   div   cstring   

原文地址:http://www.cnblogs.com/Mrsrz/p/7629374.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!