【矩阵乘法加速递推】 SSL 1531 斐波那契数列

大意

f [ i ] = f [ i − 2 ] + f [ i − 1 ] + n + 1 f[i]=f[i-2]+f[i-1]+n+1 f[i]=f[i2]+f[i1]+n+1
f [ 1 ] = f [ 2 ] = 1 f[1]=f[2]=1 f[1]=f[2]=1 f [ n ]   m o d   9973 f[n]\ mod\ 9973 f[n] mod 9973


思路

考虑矩阵乘法加速递推

观察发现,这简直就是一个矩阵乘法板子,我们从这个方向想即可

首先因为有四个系数,所以我们建立一个 4 × 4 4\times 4 4×4的矩阵,然后去想每个数需要变成几就非常容易想到中间矩阵了

f [ i − 2 ] → f [ i − 1 ] = 1 f[i-2]→f[i-1]=1 f[i2]f[i1]=1
f [ i − 1 ] → f [ i ] f[i-1]→f[i] f[i1]f[i]
i → i + 1 i→i+1 ii+1
1 → 1 1→1 11
这样,所有四个系数的转移都想好了,现在只需按这个规则转移即可,如图
啦啦啦


代码

#include<cstdio>
#include<cstring>
#define ymw 9973
using namespace std;int n;
struct node{int a[4][4],r,c;};
inline node mul(node x,node y)//矩阵乘法
{
	node z;
	memset(&z,0,sizeof(z));
	for(register int i=0;i<x.r;i++)
	 for(register int j=0;j<y.c;j++)
	  for(register int k=0;k<x.c;k++)
	z.a[i][j]=(z.a[i][j]+x.a[i][k]*y.a[k][j])%ymw;
	z.r=x.r;z.c=y.c;
	return z;
}
inline int ksm(register int y)
{
	node x,ans;
	memset(&x,0,sizeof(x));
	memset(&ans,0,sizeof(ans));
	x.r=x.c=ans.r=ans.c=4;
	x.a[1][0]=1;
	x.a[0][1]=x.a[1][1]=x.a[2][1]=x.a[3][1]=1;
	x.a[2][2]=x.a[3][2]=1;
	x.a[3][3]=1;
	ans.a[0][0]=ans.a[0][1]=ans.a[0][3]=1;
	ans.a[0][2]=3;//注意,初始是从第三个矩阵开始算
	while(y)
	{
		if(y&1) ans=mul(ans,x);
		x=mul(x,x);
		y>>=1;
	}
	return ans.a[0][0];
}
signed main()
{
	scanf("%d",&n);
	printf("%d",ksm(n-1));
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值