P1349 广义斐波那契数列(矩阵加速)

P1349 广义斐波那契数列

题目描述

广义的斐波那契数列是指形如an=pan-1+qan-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。

简单的矩阵加速

推导很好推吧

两项式一般也就(2*2)矩阵

自己手玩一下就能推出来

[egin{pmatrix} a[n],a[n-1] end{pmatrix}=egin{pmatrix} a[n-1],a[n-2]end{pmatrix} imes egin{bmatrix} p,1\q,0 end{bmatrix} ]

从而可以得到

[egin{pmatrix} a[n],a[n-1] end{pmatrix}=egin{pmatrix} a[2],a[1]end{pmatrix} imes egin{bmatrix} p,1\q,0 end{bmatrix}^{n-2} ]

#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
struct node {
    int m[40][40];
}a,b;
int mod;
node mul(node x,node y) {
    node c= {};
    for(int i=1; i<=2; ++i)
        for(int j=1; j<=2; ++j)
            for(int k=1; k<=2; ++k)
                c.m[i][j]=(c.m[i][j]+(x.m[i][k]*y.m[k][j])%mod)%mod;
    return c;
}
node fpow(node ss,int p) {
    node ans= {};
    ans.m[1][1]=ans.m[2][2]=1;
    while(p) {
        if(p&1) ans=mul(ans,ss);
        ss=mul(ss,ss);
        p>>=1;
    }
    return ans;
}
int p,q,n;
main() {
    cin>>b.m[1][1]>>b.m[2][1]>>a.m[1][2]>>a.m[1][1]>>n>>mod;
    b.m[1][2]=1;
    if(n==1||n==2) {
        cout<<a.m[n][1]<<"
";
        return 0;
    }
    b=fpow(b,n-2);
    a=mul(a,b);
    cout<<a.m[1][1]<<"
";
    return 0;
}
原文地址:https://www.cnblogs.com/dsrdsr/p/9349158.html