标签:mat 题解 ll Fibonacci res include dp
【题解】Fibonacci前n项和
题目大意
大家知道Fibonacci数列吧,f[1]=1,f[2]=1,f[3]=2,f[4]=3……也就是f[n]=f[n-1]+f[n-2]。现在问题很简单,输入n和m,求前n项和取模m。
数据范围
1<=n<=2000000000 1<=m<=1000000010
分析
数据范围很大,所以递推肯定是会爆炸的。
我们考虑用矩阵优化,(没有做过斐波那契数列?那还不快去做!)但是,这下又出现了一个问题,那就是我们如果直接用矩阵乘法的话只能求出一个数列的第n项,如何求出前n项的和......嗯,这是个问题。
但是,出题人是不可能自己坑害自己的!所以,这其中肯定是有什么规律可言。
我们发现:
\[dp[i]=dp[i-1]+dp[i-2] \]那么,对于\(dp[n]\),我们能知道:
\[dp[n]=dp[n-1]+dp[n-2]=dp[n-2]+dp[n-3]+dp[n-3]+dp[n-4]=dp[n-2]+dp[n-3]+......=dp[1]+\sum _{i=1}^{n-2} dp[i] \]也就是说,我们求出来的第n项,其实就是\(dp[1]到dp[n-2]\)的和再加上1。
这就好办了,我们只要求出第n+2项的值再减去1即可。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
ll n,m;
struct Matrix {
ll mat[2][2];
void clear() {
memset(mat,0,sizeof(mat));
}
void idenaty() {
clear();
for(int i=0;i<2;i++)
mat[i][i]=1;
}
};
Matrix mul(Matrix a,Matrix b) {
Matrix res;
res.clear();
for(int i=0;i<2;i++) {
for(int j=0;j<2;j++) {
for(int k=0;k<2;k++) {
res.mat[i][j]=(res.mat[i][j]+a.mat[i][k]*b.mat[k][j]%m)%m;
}
}
}
return res;
}
Matrix power(Matrix x,ll p) {
Matrix res;
res.idenaty();
while(p) {
if(p&1) res=mul(res,x);
x=mul(x,x);
p>>=1;
}
return res;
}
Matrix a;
int main() {
scanf("%lld%lld",&n,&m);
a.mat[0][0]=1,a.mat[0][1]=1;
a.mat[1][0]=1,a.mat[1][1]=0;
Matrix res=power(a,n+1);//求出第n+2项
printf("%lld",res.mat[0][0]-1);
return 0;
}
/*
dp[i]= 1 * dp[i-1] + 1*dp[i-2]
dp[i-1]= 1 * dp[i-1] + 0*dp[i-2]
*/
标签:mat,题解,ll,Fibonacci,res,include,dp 来源: https://www.cnblogs.com/lxxwxxxxx/p/15579372.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。