HDU --- 4549 M斐波那契数列 【费马小定理+矩阵快速幂】

来源:互联网 发布:mysql front 编辑:程序博客网 时间:2024/05/17 03:44

传送门
思路: 通过把前面几项手推出来可以发现, 其次方项符合斐波那契数列, 又因为数据非常大, 所以就可以想到用矩阵快速幂去求得次方项, 需要注意的就是我们求的是次方, 而答案是取的某个数的该次方, 而a^b % p != a^(b%p) % p, 所以就需要加费马小定理去 % 注意使用费马小定理的条件p 要为质数! 所以就是 a^(p-1) % p = 1, 所以我们就可以让b% (p - 1 ).

AC Code

#include<bits/stdc++.h>#define CLR(x) memset(x,0,sizeof(x))#define ll long long int#define PI acos(-1.0)#define db doubleusing namespace std;const int maxn=1e5+5;const int mod = 1000000007;ll A,B,n;struct Ma{    ll a[5][5];    void cc(){        CLR(a);    }    Ma operator * (const Ma &b) const {        Ma tmp;        tmp.cc();        for(int i=0;i<2;i++){            for(int j=0;j<2;j++){                for(int k=0;k<2;k++){                    tmp.a[i][j] += (a[i][k] * b.a[k][j]);                    tmp.a[i][j] %= (mod-1);  //1e9+7 刚好是质数, 所以由费马小定理, 知道当次方//项到达1e9+6时,答案为1, 所以项数应该mod 1e9+6 , 且不会影响最终结果. 否则就会影响结果.                }            }        }        return tmp;    }}res,x;void init(){    res.cc();    x.cc();    for(int i=0;i<2;i++)        res.a[i][i]=1;    x.a[0][0] = x.a[0][1] = 1;    x.a[1][0] = 1;    x.a[1][1] = 0;}void qpow(int t){    while(t){        if(t&1) res = res * x;        x = x*x;        t >>= 1;    }}ll pow(ll t,ll k)  //这个是快速幂, 因为最后求数的几次方的时候会用到.{    ll sum = 1;    ll base = k;    while(t){        if(t&1){            sum *= base;            sum %= mod;        }        base *= base;        base %= mod;        t >>= 1;    }    return sum;}int main()  //思路找到项数对应的Fiboccai 数列中对应的次方项, 分别求出在数列中的值.最后乘在一起就行了.{    while(scanf("%lld%lld%lld",&A,&B,&n)!=EOF){        ll b[5];        b[0] = A;        b[1] = B;        if(n<2){            printf("%lld\n",b[n]);            continue;        }        ll k1=0,k2=0;        if(n<4)            k1=1;        else{            init();            qpow(n-3);            for(int i=0;i<2;i++){                k1 += res.a[i][0];                k1 %= (mod-1);   //因为是次方数, 所以是mod 1e9+6;            }        }        if(n==2){            k2=1;        }        else{            init();            qpow(n-2);            for(int i=0;i<2;i++){                k2 += res.a[i][0];                k2 %= (mod-1);            }        }        ll ans = (pow(k1,A)%mod*pow(k2,B)%mod)%mod;  //最终结果才是mod 1e9+7 ;        printf("%lld\n",ans);    }}
阅读全文
0 0
原创粉丝点击