hdu4549 斐波那契数列(乘法递推) + 欧拉定理 (快速幂,模幂)

这题的话,看a ,b 的指数,刚好可以使用斐波那契数列求解。
 加法斐波那契数列是直接在最后用(b*m.mat[0][0] + a * m.mat[1][0] ) % MOD
乘法就变成了乘方!!所以需要用到快速模幂。。
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">然后用矩阵做。</span>
 
A^B %C   这题的C是质素,而且A,C是互质的。
所以直接A^(B%(C-1)) %C
 

比较一般的结论是 A^B %C=A^( B%phi(C)+phi(C) ) %C     B>=phi(C)


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
#define MOD 1000000007
#define N 2

struct Mat
{
    long long mat[N][N];
};

Mat operator * (Mat a, Mat b)
{
    Mat c;
    memset(c.mat, 0, sizeof(c.mat));
    int i, j, k;
    for(k = 0; k < N; ++k)
    {
        for(i = 0; i < N; ++i)
        {
            if(a.mat[i][k] <= 0)  continue;   //(针对ZOJ2853)剪枝,cpu运算乘法的效率并不是想像的那么理想(加法的运算效率高于乘法,比如Strassen矩阵乘法)
            for(j = 0; j < N; ++j)
            {
                if(b.mat[k][j] <= 0)    continue;    //剪枝
                c.mat[i][j] = (c.mat[i][j] + (a.mat[i][k] * b.mat[k][j]) % (MOD - 1)) % (MOD - 1);
            }
        }
    }
    return c;
}

Mat operator ^ (Mat a, int k)
{
    Mat c;
    int i, j;
    for(i = 0; i < N; ++i)
        for(j = 0; j < N; ++j)
            c.mat[i][j] = (i == j);    //初始化为单位矩阵

    for(; k; k >>= 1)
    {
        if(k&1) c = c*a;
        a = a*a;
    }
    return c;
}

long long Pow(long long n ,long long m, int mod)
{
    long long res = 1;
    while(m >= 1)
    {
        if(m & 1)
        {
            res = (res * n ) % mod;
        }
        n = n * n % mod ;
        m >>= 1;
    }
    return res;
}

int main()
{
    int a , b , n;
    while(cin >> a >> b >> n)
    {
        Mat m;
        m.mat[0][0] = 1;
        m.mat[0][1] = 1;
        m.mat[1][0] = 1;
        m.mat[1][1] = 0;
        if(n > 1)
        {
            m = m ^ (n - 1);
         /*   for(int i = 0; i < N; ++i)
            {
                for(int j = 0; j < N; ++j)
                    cout << m.mat[i][j] <<" ";
                cout << endl;
            }
*/
            cout <<(Pow( b , m.mat[0][0] , MOD )% MOD * Pow( a , m.mat[1][0] , MOD ) )%MOD << endl;
        }
        else if(n == 0) cout << a << endl;
        else cout << b << endl;
    }
    return 0 ;
}


你可能感兴趣的:(hdu4549 斐波那契数列(乘法递推) + 欧拉定理 (快速幂,模幂))