求幂大法,矩阵快速幂,快速幂模板题--hdu4549

hdu-4549 求幂大法、矩阵快速幂、快速幂

题目

M斐波那契数列

Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 6217 Accepted Submission(s): 1902

Problem Description

M斐波那契数列F[n]是一种整数数列,它的定义如下:

F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )

现在给出a, b, n,你能求出F[n]的值吗?

Input

输入包含多组测试数据;
每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 )

Output

对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模后的值即可,每组数据输出一行。

Sample Input

0 1 0
6 10 2

Sample Output

0
60

思路

列出F_n的前几项可以知道,指数是0,1开始的斐波那契数列

代码

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdio>

using namespace std;

typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = 5;
const int MOD = 1e9 + 7;

struct M
{
    LL m[2][2];
    M(){memset(m, 0, sizeof(m));}
};

LL Eular(LL n)
{
    LL ret = n;
    for(int i = 2;i * i <= n;++i)
    {
        if(n % i == 0)
        {
            ret = ret - ret / i;
            while(n % i == 0)
                n /= i;
        }
    }
    if(n > 1)
        ret = ret - ret / n;
    return ret;
}

LL m = Eular(MOD);

M mul(M a, M b)
{
    M ret;
    for(int i = 0;i < 2;++i)
        for(int j = 0;j < 2;++j)
            for(int k = 0;k < 2;++k)
            ret.m[i][j] = (ret.m[i][j] + a.m[i][k] * b.m[k][j] % m) % m;//注意这里因为是幂,所以是模Eular(MOD)
    return ret;
}

M M_pow(M a, int b)
{
    M ret;
    ret.m[0][0] = 1, ret.m[1][1] = 1;
    while(b)
    {
        if(b & 1)
            ret = mul(ret, a);
        a = mul(a, a);
        b >>= 1;
    }
    return ret;
}

LL q_pow(LL a, LL b)
{
    LL ret = 1;
    a %= MOD;
    while(b)
    {
        if(b & 1)
            ret = (ret * a) % MOD;
        a = (a * a) % MOD;
        b >>= 1;
    }
    return ret;
}

int main()
{
    LL a, b, n;
    while(cin >> a >> b >> n)
    {
        if(!n)
        {
            cout << a % MOD << endl;
            continue;
        }
        M f, k;
        f.m[0][0] = 1;
        k.m[0][0] = k.m[0][1] = k.m[1][0] = 1;
        f = mul(f, M_pow(k, n - 1));
        //cout << f.m[0][1] << " " << f.m[0][0] << endl;
        cout << ((q_pow(a, f.m[0][1] % m) % MOD) * (q_pow(b, f.m[0][0] % m) % MOD)) % MOD << endl;
    }
    return 0;
}

posted @ 2019-03-29 20:27  谁知道你啊啊啊  阅读(197)  评论(0编辑  收藏  举报