矩阵快速幂之斐波那契数列

题目:

大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2。

现在问题很简单,输入 nn 和 mm,求 fnfn 的前 nn 项和 SnmodmSnmodm。

输入格式

共一行,包含两个整数 nn 和 mm。

输出格式

输出前 nn 项和 SnmodmSnmodm 的值。

数据范围

1≤n≤20000000001≤n≤2000000000,
1≤m≤10000000101≤m≤1000000010

输入样例:

5 1000

输出样例:

12

 

思路整理:

矩阵公式推理:

Fn = [fn  fn+1]

Fn+1 = [fn+1  fn+2]          fn+2 = fn+1 + fn

     = [fn  fn+1] * [0  1]

                    [1  1]

X = {

    {0, 1}

    {1, 1}      }

Fn = [fn  fn+1]

Fn+1 = [fn  fn+1]*X

Fn+1 = Fn * X

Fn = Fn-1 * X (n>=2)

...

F3 = F2 * X = F1 * X * X

F2 = F1 * X

->  Fn = F1 * X^(n-1)

    F1 = [1  1]

    Fn = [1  1] * X^(n-1)

---------------------求和分割线------------------------------------

Fn = [fn  fn+1  sn]  

Fn+1 = [fn+1  fn+2  sn+1]

     = Fn * { [0  1  0]

              [1  1  1]

              [0  0  1] }

X = { [0  1  0]

      [1  1  1]

      [0  0  1] }

F2 = F1 * X = [1  1  2]*X

F3 = F2 * X = F1 * X * X

...

Fn = F1 * X^(n-1)

   = [1  1  1] * { [0  1  0]

                   [1  1  1]

                   [0  0  1] } ^(n-1)

sn = Fn[2]

 代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL maxn = 2e9 + 7;
#define fori(i,n) for(int i = 0; i < n; i++)
LL n, m;
LL f1[3] = {1, 1, 1};
LL x[3][3] = {
    {0, 1, 0},
    {1, 1, 1},
    {0, 0, 1}
};
LL res[3][3];

void matrixMul_2(LL a[][3], LL b[][3], LL c[][3])
{
    LL ans[3][3];

    fori(i, 3)
    {
        fori(j, 3)
        {
            ans[i][j] = 0;
            fori(k, 3)
            {
                ans[i][j] = (ans[i][j] + a[i][k]*b[k][j]) % m;
            }
        }
    }
    memcpy(c, ans, sizeof(ans));
}
void matrixMul_1(LL a[], LL b[][3])
{
    LL c[3];
    fori(i, 3)
    {
        c[i] = 0;
        fori(j, 3)
    {
        c[i] = (c[i] + a[j] * b[j][i]) % m;
    }
    }
    memcpy(a, c, sizeof(c));
}

int main() 
{
    scanf("%lld%lld", &n, &m);
    n--;
    while(n)
    {
        if(n&1) matrixMul_1(f1, x);
        n>>=1;
        matrixMul_2(x, x, x);
    }
    printf("%lld", f1[2]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值