2019.09.01 日常总结

开学咯……

一本通1643&LOJ10221:

【题意】:求斐波那契数列前n项的和模m的值(1\leq n \leq 2\times 10^9,1\leq m \leq 1\times 10 ^ 9 + 10)

【思路】:记斐波那契数列第i项为f[i],记斐波那契数列前n项的和为s[i],即有s[i] = \sum ^ n _ {j = 1} f[j]

我们有以下几个式子:

1.s[n]=1\times s[n-1]+1\times f[n]+0\times f[n-1]

2.f[n + 1] = 0 \times s[n - 1] + 1 \times f[n] + 1 \times f[n - 1]

3.f[n] = 0 \times s[n - 1] + 1 \times f[n] + 0 \times f[n - 1]

所以我们可以构造的矩阵如下:

\begin{pmatrix} s[n] \\ f[n+1] \\f[n] \end{pmatrix}=\begin{pmatrix} & 0 & 1 & 0 & \\ & 1 & 1 & 1 & \\ & 0 & 0 & 1 & \end{pmatrix}\times \begin{pmatrix} s[n-1] \\f[n] \\f[n-1] \end{pmatrix}

至于,为什么是\begin{pmatrix} 0 & 1 & 0 \\ 1 & 1 & 1 \\ 0 & 0 & 1 \end{pmatrix},是因为矩阵乘法,行列相乘

【代码】:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5;ll mod;
struct node{
	ll g[N][N];
	node(){
		memset(g,0,sizeof(g));
	}//初始化全部为0
	void init(){
		for(int i=1;i<4;i++)
		g[i][i]=1;
	}//构造一定单位矩阵
	node operator * (node b){
		node c;int i,j,k;
		for(i=1;i<4;i++)
		for(j=1;j<4;j++)
		for(k=1;k<4;k++)
		c.g[i][k]=(c.g[i][k]+g[i][j]*b.g[j][k])%mod;
		return c;
	}//定义矩阵乘法的操作
}f;int n;
node ksm(int k){
	node res,tmp=f;res.init();
	while (k){
		if (k&1) res=res*tmp;
		tmp=tmp*tmp;k>>=1;
	}
	return res;
}//重定义了*号后,使用起来就像使用int一样方便
inline ll answer(){
	if (n==1) return 1ll;node t=ksm(n-1);//记得是ksm(n-1)哦
	return (t.g[1][3]+t.g[2][3]+t.g[3][3])%mod;
}
int main(){
	cin>>n>>mod;//输入
	f.g[1][1]=0;f.g[1][2]=1;f.g[1][3]=0;
	f.g[2][1]=1;f.g[2][2]=1;f.g[2][3]=1;
	f.g[3][1]=0;f.g[3][2]=0;f.g[3][3]=1;//初始化一个矩阵
	cout<<answer();
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值