zoukankan      html  css  js  c++  java
  • 求幂大法,矩阵快速幂,快速幂模板题--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;
    }
    
    
  • 相关阅读:
    Android 源码阅读之MMS细读TransactionService.java
    [Java2 入门经典]第16章 线程
    Android 源码阅读之建立3G网络流程
    从架构上看Android多媒体播放器
    Android 开发日志之仿三星Launcher
    非常适合OA系统的菜单
    模拟动网当前位置下拉菜单
    模拟windows菜单选项卡效果
    TreeView的各种操作
    ASCII表
  • 原文地址:https://www.cnblogs.com/shuizhidao/p/10623740.html
Copyright © 2011-2022 走看看