洛谷1349 广义斐波那契数列 【矩阵乘法】

来源:互联网 发布:苹果 app 办公软件 编辑:程序博客网 时间:2024/05/18 01:19
洛谷1349 广义斐波那契数列

题目描述

广义的斐波那契数列是指形如an=p*an-1+q*an-2的数列。今给定数列的两系数p和q,以及数列的最前两项a1和a2,另给出两个整数n和m,试求数列的第n项an除以m的余数。

输入输出格式

输入格式:

输入包含一行6个整数。依次是p,q,a1,a2,n,m,其中在p,q,a1,a2整数范围内,n和m在长整数范围内。

输出格式:

输出包含一行一个整数,即an除以m的余数。

输入输出样例

输入样例#1:

1 1 1 1 10 7

输出样例#1:

6

说明

数列第10项是55,除以7的余数为6。

 

 

【思路】

  矩阵乘法。

  n最大为maxlongint所以枚举肯定会有TLE。

  这里用到了矩阵乘法。大体思想:因为每次的求解规则相同,所以可以构造一个转移矩阵,使得每个点与该矩阵相乘即可直接得出最终该点的位置。

  开始矩阵B:

      a2 a1

构造矩阵如下:

      P 1

      Q 0

  (一次转换后为p*a2+q*a1,a2 )

  因为要进行n-2次相同的转换所以用快速幂求解转换n-2次后的A’ 。

  ans=B*A'

 

  注意: 矩阵乘法的顺序不能更改,否则可能不满足乘法要求。

         LL 与 LL的乘法可能会爆精度,可以转化为小数相加的形式。

 

代码思想源于洛谷题解。

【代码】

 

 

 1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4  5 typedef long long LL; 6 const int delen=23,delta=1<<23,deltb=delta-1; 7 LL n,m,p,q,a1,a2; 8  9 LL Add(LL x,LL y) {10     x+=y;11     if(x>=m) x-=m;12     return x;13 }14 15 LL multi(LL x,LL y) {  //对于long long型的 乘法+模 防止越界 16     LL ans=0;17     while(y) {18         if(y&deltb) ans=Add(ans,x*(y&deltb)%m);19         x=x*delta%m;20         y>>=delen;21     }22     return ans;23 }24 25 struct Matrix{26     int r,c;27     LL N[5][5];28     Matrix operator *(const Matrix& rhs) const{29         Matrix tmp={};30         tmp.r=r, tmp.c=rhs.c;31         for(int i=0;i<tmp.r;i++)32           for(int j=0;j<tmp.c;j++) {33                 for(int k=0;k<c;k++)  tmp.N[i][j] += multi(N[i][k],rhs.N[k][j]);34                 tmp.N[i][j] %= m;35           }36         return tmp;37     }38     39     Matrix pow(LL p) const{40         Matrix ans={} , tmp=*this;41         ans.r=ans.c=r;42         for(int i=0;i<r;i++) ans.N[i][i]=1;43         while(p) {44             if(p&1) ans=ans*tmp;45             tmp=tmp*tmp;46             p>>=1; 47         }48         return ans;49     }50 };51 52 int main() {53     cin>>p>>q>>a1>>a2>>n>>m;54     Matrix A,B;55     A.r=A.c=2;56     A.N[0][0]=p , A.N[1][0]=q , A.N[0][1]=1 , A.N[1][1]=0; //057     A=A.pow(n-2);58     59     B.r=1 , B.c=2;60     B.N[0][0]=a2,B.N[0][1]=a1;61     62     B=B*A;    //B*A63     64     cout<<B.N[0][0]%m;65     return 0;66 }

 

0 0