HDU4549_M斐波那契数列_斐波那契数列&费马小定理

来源:互联网 发布:小米手机一直2g网络 编辑:程序博客网 时间:2024/05/20 09:08

题意

M斐波那契数列F[n]是一种整数数列,它的定义如下:
F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )
现在给出a, b, n,你能求出F[n]的值吗?

思路

写出几项便发现,a 的指数是 fib[n - 1], b 的指数是 fib[n],实际上是求斐波那契数列+快速幂。

费马小定理

特别的,mod 是素数,故可以利用费马小定理。
a^(p-1)≡1(mod p)
特别注意!本题中应用费马小定理的指数是通过矩阵快速幂求得的。在快速幂中的mod 都得是 mod - 1!而不能在求出结果后搞一个 % (mod - 1)!这太傻了。是的,太傻了。

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=4549

AC代码

#include<cstdio>#include<iostream>#include<vector>using namespace std;typedef long long LL;typedef vector<LL> vec;typedef vector<vec> mat;int mod = 1000000007;int a, b, n;mat mul(mat A, mat B){    mat C(A.size(), vec(B[0].size()));    for(int i= 0; i< A.size(); i++)        for(int k= 0; k< B.size(); k++)            for(int j= 0; j< B[0].size(); j++)                C[i][j] = (C[i][j] + A[i][k] * B[k][j] % mod) % mod;    return C;}mat pow(mat A, LL n){    mat B(A.size(), vec(A.size()));    for(int i= 0; i< A.size(); i++)        B[i][i] = 1;    while(n > 0)    {        if(n & 1) B = mul(B, A);        A = mul(A, A);        n >>= 1;    }    return B;}int main(){    while(scanf("%d %d %d", &a, &b, &n) != EOF)    {        if(n == 0){            cout << a % mod << endl;            continue;        }        mod = 1000000006;//mod - 1        mat A(2, vec(2));        A[0][0] = A[0][1] = A[1][0] = 1, A[1][1] = 0;        A = pow(A, n - 1);        mod ++;        mat t1 (1, vec(1));        t1[0][0] = a;        t1 = pow(t1, A[1][0]);        mat t2 (1, vec(1));        t2[0][0] = b;        t2 = pow(t2, A[0][0]);        cout << t1[0][0] * t2[0][0] % mod << endl;    }    return 0;}
原创粉丝点击