HDU 4549 M斐波那契数列【矩阵快速幂】

M斐波那契数列

Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)

Total Submission(s) : 4 Accepted Submission(s) : 1

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

Source

2013金山西山居创意游戏程序挑战赛——初赛(2)

指数呈斐波那契规律,注意指数可能很大,需要使用费马小定理

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define ll long long int
const ll p = 1e9 + 7;
const int maxn = 2;
struct node {
    ll a[2][2];
    void Clear() {
        memset(a, 0, sizeof a);
    }
};
node mul(node a, node b)
{
    node c; int i, j,k;
    for (i = 0; i<maxn; i++)
    {
        for (j = 0; j<maxn; j++)
        {
            c.a[i][j] = 0;
            for (k = 0; k<maxn; k++)
                c.a[i][j] += (a.a[i][k] * b.a[k][j]) % (p - 1);
            c.a[i][j] %= (p - 1);
        }
    }
    return c;
}
node get_f(ll x)
{
    node f;
    f.Clear();
    f.a[0][0] = 1;
    f.a[1][1] = 1;
    node tmp;
    tmp.Clear(); tmp.a[1][1] = 1; tmp.a[0][1] = 1; tmp.a[1][0] = 1;
    while (x) {
        if (x % 2 == 1) {
            f = mul(f, tmp);
        }
        tmp = mul(tmp, tmp);
        x >>= 1;
    }
    return f;
}
ll qkm(ll a, ll b) {
    if (b == 1) return a;
    ll ans = 1;
    a %= p;
    while (b)
    {
        if (b % 2)
            (ans *= a) %= p;
        (a = a * a) %= p;
        b >>= 1;
    }
    return ans;
}
int main()
{
    ll a, b, n;
    while (scanf("%lld%lld%lld", &a, &b, &n) != EOF)
    {
        /*if (n == 0) { cout << a << endl; continue; }
        if (n == 1) { cout << b << endl; continue; }
        if (n == 2) { cout << a * b%p << endl; continue; }
        node x = get_f(n - 2);
        ll z = x.a[0][0];
        x = get_f(n - 3);
        ll y = x.a[0][0];
        a = qkm(a, y); a %= (p-1);
        b = qkm(b, z); b %= (p-1);
        printf("%lld\n", a*b%p);*/
        node x = get_f(n);
        ll ans = (qkm(a, x.a[0][0])*qkm(b, x.a[1][0])) % p;
        cout << ans << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值