斐波那契

矩阵快速幂、快速乘还有鸡贼。

历届试题 斐波那契  

时间限制:1.0s   内存限制:256.0MB

   

问题描述

  斐波那契数列大家都非常熟悉。它的定义是:

  f(x) = 1 .... (x=1,2)
  f(x) = f(x-1) + f(x-2) .... (x>2)

  对于给定的整数 n m,我们希望求出:
  f(1) + f(2) + ... + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
  公式如下


  但这个数字依然很大,所以需要再对p 求模。

输入格式

  输入为一行用空格分开的整数 n m p (0 < n, m,p < 10^18)

输出格式

  输出为1个整数,表示答案

样例输入

2 3 5

样例输出

0

样例输入

15 11 29

样例输出

25


大佬的文章:点击打开链接


本菜鸡不会写这么复杂的,有空再来补上,,,

当m太大了longlong存不下了那么取模意义就不大了,m小的时候就直接套公式算吧。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

ll n, m, p;
const ll N = 2, M = 2, P = 2;
struct Matrix{ll m[N][N];};

Matrix A={1,1,1,0};
Matrix I={1,0,0,1};

ll mul(ll a, ll b, ll MOD){
    a = (a % MOD + MOD) % MOD;
    b = (b % MOD + MOD) % MOD;

    ll ans = 0;
    if(a < b)
        swap(a, b);
    while(b > 0){
        if(b & 1)
            ans = (ans + a) % MOD;
        a = (a + a) % MOD;
        b >>= 1;
    }
    return ans;
}

Matrix multi(Matrix &a,Matrix &b, ll MOD)
{
    Matrix ans;
    for(int i=0;i<N;i++)//i, j控制行列
        for(int j=0;j<M;j++)
        {
            ans.m[i][j]=0;
            for(int k=0; k<P; k++){
                ans.m[i][j] += mul(a.m[i][k], b.m[k][j], MOD);
                ans.m[i][j] %= MOD;
            }
        }
    return ans;
}
Matrix power(Matrix &a, ll k, ll MOD)
{
    Matrix ans=I,z=a;

    while(k > 0)
    {
        if(k&1){
            ans=multi(ans,z, MOD);
        }
        k>>=1;
        z=multi(z,z, MOD);
    }
    return ans;
}

ll solve(ll n, ll MOD)
{
    Matrix ans=power(A,n-1, MOD);

    return ans.m[0][0];
}
int main()
{
    //freopen("input5.txt", "r", stdin);
    scanf("%lld%lld%lld", &n, &m, &p);

    if(m > 100){
        ll ans = (solve(n + 2, p) - 1);

        printf("%lld", (ans % p + p) % p);
    }else{
        ll fm = solve(m, 1e18);
        ll ans = (solve(n + 2, 1e18) - 1) % fm;
        printf("%lld", ans % p);
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值