zoukankan      html  css  js  c++  java
  • 洛谷1349 广义斐波那契数列 【矩阵乘法】

    洛谷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; //0
    57     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*A
    63     
    64     cout<<B.N[0][0]%m;
    65     return 0;
    66 }
  • 相关阅读:
    【皇甫】☀ 亮眼的颜色
    【皇甫】☀独一无二
    【皇甫】☀唯一
    【皇甫】☀一本好书 你值得浏览
    【皇甫】☀标题自己起 进来看像啥就是啥
    【皇甫】☀说说那些选择器
    【皇甫】☀标题被你吃了
    【皇甫】☀四套写入方案(仅供参考)
    【皇甫】☀内侧小解析---小行动(2)
    【皇甫】☀内侧小解析---小行动(1)
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4882141.html
Copyright © 2011-2022 走看看