Sicily 1863. Elegant fibonacci numbers again (斐波那契+矩阵快速幂)

题意:

Fibonacci数列,f[0]=0, f[1]=1, f[n] = f[n-2]+f[n-1],n>1

给出n(0 <= n < 2^32)和m,求f[n] mod m.

 

解题思路:

n太大,所以不能用O(n)的循环递推计算

 

结论:对于矩阵|1 1|,和矩阵|Fn   Fn-1|,两者相乘之后得到新矩阵|Fn+1  Fn  |,Fn为第n个Fibonacci数

                        |1 0|             |Fn-1 Fn-2|                                         |Fn    Fn-1|

 

于是我们就可以用O(logn)的快速幂求模+矩阵乘法算出f[n].

快速幂的过程:a^b =

1, b==0

a, b==1

a^(b/2) * a^(b/2), b 为偶

a*a^(b-1), b为奇



#include<iostream>
#include<cstdio>
using namespace std;

struct Node
{
    int arr[2][2];
}o;

Node MUL(Node a, Node b,const int &m)
{
    Node tmp;
    tmp.arr[0][0] = (a.arr[0][0]*b.arr[0][0] + a.arr[0][1]*b.arr[1][0]) % m;
    tmp.arr[0][1] = (a.arr[0][0]*b.arr[0][1] + a.arr[0][1]*b.arr[1][1]) % m;
    tmp.arr[1][0] = (a.arr[1][0]*b.arr[0][0] + a.arr[1][1]*b.arr[1][0]) % m;
    tmp.arr[1][1] = (a.arr[1][0]*b.arr[0][1] + a.arr[1][1]*b.arr[1][1]) % m;
    return tmp;
}

Node exp(Node mat, int n, const int &m)
{
    if(n == 1) return o;
    
    if(n & 1)
    {
        return MUL(o, exp(mat,n-1,m), m);
    }
    else
    {
        Node tmp = exp(mat,n>>1, m);
        return MUL(tmp,tmp,m);
    }
}

int main()
{
    o.arr[0][0] = o.arr[0][1] = o.arr[1][0] = 1; o.arr[1][1] = 0;
    int cas;
    scanf("%d",&cas);
    while(cas --)
    {
        int n,m;
        scanf("%d%d",&n,&m);

        if(n == 0)
        {
            printf("0\n");
            continue;
        }
        
        Node f = o;
        f = exp(f,n,m);
        
        printf("%d\n",f.arr[0][1] % m);
    }
}                                 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值