【NOIP2016提高A组模拟7.15】斐波那契数列(矩阵乘法)

来源:互联网 发布:百度云管家mac版 编辑:程序博客网 时间:2024/05/17 02:23

题目

这里写图片描述

数据

这里写图片描述

小结

30%做法不知道怎么做出来的~暴力都能60吧。
60%暴力咯~
100%
然后就是比较恶心的一个东西:叫做“矩阵乘法”。
这东西大家应该不用理解太久,连我这个蒟蒻都只是理解了半个小时~
不讲废话:
我们的斐波那契数列是这样的:
0 1 1 2 3 5 8 13…….
我们一个矩阵,只有两个数,就是我们当前的这个以及前一个,这样就可以推出下一个了。
推一推:
这里写图片描述
发现,答案的第一位就是原始数的第二位,那么原始数的第一位对答案的第一位是没有贡献的,所以:
这里写图片描述
我们考虑后面,第二位是前面两位之和,那么就两个都有贡献咯~
这里写图片描述
这样这个矩阵就推出来啦,我们就可以用快速幂的思想去做,其实就是乘这个矩阵n-1次。

#include<cstdio>#include<iostream>using namespace std;long long n,m;long long a[3],b[3,3],c[3],d[3,3];void ksm(long long n,long long p){    int i,j,k;    while(n)    {        if(n&1)         {            c[1]=0;c[2]=0;            for (i=1;i<=2;++i)                for (j=1;j<=2;++j)                    (c[i]+=a[j]*b[j,i])%=p;            a[1]=c[1];a[2]=c[2];        }        n>>=1;        d[1,1]=0;d[1,2]=0;        d[2,1]=0;d[2,2]=0;        for (i=1;i<=2;++i)            for (j=1;j<=2;++j)                for (k=1;k<=2;++k)                    (d[i,j]+=b[i,k]*b[k,j])%=p;        b[1,1]=d[1,1];b[1,2]=d[1,2];        b[2,1]=d[2,1];b[2,2]=d[2,2];    }}int main(){    scanf("%lld%lld",&n,&m);    b[1,1]=0;    b[1,2]=1;    b[2,1]=1;    b[2,2]=1;    a[1]=1;    a[2]=1;    ksm(n-1,m);    printf("%lld\n",a[2]);}
阅读全文
0 0
原创粉丝点击