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

来源:互联网 发布:java引用文件 编辑:程序博客网 时间:2024/05/17 04:29

思路:

通过列出几项我们就可以发现ab的指数是斐波那契数列。然后博主就开(智)心(障)的用矩阵快速幂算指数了。。
却忘了一件事。。。谁说的取模对指数封闭的啊???md疯狂wa了六七次。
取模对乘法封闭但不意味着指数你可以直接取模啊。。

正解是根据费马小定理:

ab=cmodp

gcd(a,p)=1 并且p是素数的时候,有:ap1=1modp 也就是说,指数上循环节为0 1 2 。。。。p-1,所以我们可以对指数模(1e9+7-1)。

好了,结果出来了。

#include <cstdio>#include <iostream>#include <string.h>#include <queue>#include <algorithm>typedef long long int lli;using namespace std;const int mod = 1000000007;const int n = 2;struct mat{    lli ma[n][n];};mat operator * (mat &a,mat &b){    mat c;    const int mm = mod-1;    memset(c.ma,0,sizeof(c.ma));    for(int k=0;k<n;++k){        for(int i=0;i<n;++i){            for(int j=0;j<n;++j){                c.ma[i][j] += a.ma[i][k]%mm*(b.ma[k][j]%mm)%mm;                c.ma[i][j] %= mm;            }        }    }    return c;}mat qp(mat a,lli k){    mat c;    for(int i=0;i<n;++i){        for(int j=0;j<n;++j){            c.ma[i][j] = (i==j);        }    }    for(;k;k>>=1){        if(k&1) c=c*a;        a = a*a;    }    return c;}lli qp(lli a,lli x){    lli res = 1;a %= mod;    for(;x;x>>=1){        if(x&1){            res *= a;res %= mod;        }        a = a*a%mod;    }    return res;}int main(){    int a,b,n;    while(~scanf("%d%d%d",&a,&b,&n)){        mat zuo = {1,0, 0,0};        mat base = {1,1, 1,0};        if(n == 0){            printf("%d\n",a%mod);            continue;        }        else{            base = qp(base,n-1);            lli a1 = base.ma[0][1],b1 = base.ma[0][0];            lli ans = qp(a,a1)%mod;            ans = (ans*qp(b,b1))%mod;            printf("%lld\n",ans);        }    }}
阅读全文
1 0
原创粉丝点击