【洛谷】P1349广义斐波那契

题目链接:https://www.luogu.org/problemnew/show/P1349

 

 

题意:现在定义fib数列为 an = p * an-1 + q * an-2求第n项%m的答案。

 

题解:

\begin{pmatrix} p & 1\\ q & 0 \end{pmatrix} *

\begin{pmatrix} f(n-1)& f(n-2) \end{pmatrix} =

\begin{pmatrix} p*f(n-1) + q*f(n-2)& f(n-1) \end{pmatrix}=

\begin{pmatrix} f(n)& f(n-1) \end{pmatrix}

这题有个玄学mod。矩阵乘法的时候记得要多mod一次。

代码:

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define ll long long
 6 const int maxn = 3;
 7 
 8 ll n,mod;
 9 
10 //矩阵结构体 
11 struct Matrix{
12     ll a[maxn][maxn];
13     void init(){    //初始化为单位矩阵 
14         memset(a, 0, sizeof(a));
15         for(int i = 1; i <= maxn;i++){
16             a[i][i] = 1;
17         }
18     }
19 };
20 
21 //矩阵乘法 
22 Matrix mul(Matrix a, Matrix b){
23     Matrix ans;
24     for(int i = 1;i <= 2;++i){
25         for(int j = 1;j <= 2;++j){
26             ans.a[i][j] = 0;
27             for(int k = 1;k <= 2;++k){
28                 ans.a[i][j] = ans.a[i][j] % mod + a.a[i][k] * b.a[k][j] % mod;
29                 ans.a[i][j] %= mod;
30             }
31         }
32     } 
33     return ans;
34 }
35 
36 //矩阵快速幂 
37 Matrix qpow(Matrix a,ll b){
38     Matrix ans;
39     ans.init();
40     while(b){
41         if(b & 1)
42             ans = mul(ans,a);
43         a = mul(a,a);
44         b >>= 1;
45     }
46     return ans;
47 }
48 
49 void print(Matrix a){
50     for(int i = 1; i <= n;++i){
51         for(int j = 1;j <= n;++j){
52             cout << a.a[i][j]%mod<< " ";
53         }
54         cout << endl;
55     }
56 }
57 
58 int main(){
59     ll p,q,a1,a2;
60     cin>>p>>q>>a1>>a2>>n>>mod;
61     if(n == 1){
62         cout<<a1%mod<<endl;
63         return 0;
64     }
65     if(n == 2){
66         cout<<a2%mod<<endl;
67         return 0;
68     }
69     Matrix base;
70     Matrix ans;
71     ans.a[1][1] = a2;ans.a[1][2] = a1;
72 
73     base.a[1][1] = p;base.a[1][2] = 1;
74     base.a[2][1] = q;base.a[2][2] = 0;
75 
76     ans = mul(ans,qpow(base,n-2));
77     //print(ans);
78     cout<<ans.a[1][1]%mod<<endl;
79     return 0;
80 }

 

转载于:https://www.cnblogs.com/Asumi/p/9755501.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值