zoukankan      html  css  js  c++  java
  • 2013金山西山居创意游戏程序挑战赛——初赛(2) B M斐波那契数 (hdu 4549 )


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

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

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


    思路:首先我们很容易得F[n]的通项公式,对F[n]=a^(f[n-1])*b^(f[n]),其中f[n]为斐波那契数列的第n项。由于我们要求的n很大(最大可达到10^9),所以我们不能直接求,时我们可以用矩阵加速用O(logn)的复杂度来求f[n],然后再用乘方快速幂求最终的结果。但是我们这里要求的结果是模上1000000007后(设为mod)的值,所以在矩阵加速的时候不能直接模上mod。这里用到了一个数论的知识,就是a,b互质,则a^(b-1)%b==1,因为mod是一个素数,所以对于任何a,b(a,b<=10^9),都与mod互质,所以我们最终即a^(f[n-1]%(mod-1))*b^(f[n]%(mod-1))%mod,这下就可以用矩阵快速幂来求解了。

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <string.h>
    #define maxn 3
    #define mod 1000000006
    using namespace std;
    typedef long long LL;
    LL c[100][maxn][maxn];
    LL ans[maxn][maxn];
    int m=2;
    void init(LL a[maxn][maxn],LL b[maxn][maxn], LL c[maxn][maxn])
    {
        int i,j,k;
        LL tmp[maxn][maxn];
        memset(tmp,0,sizeof(tmp));
        for(i=1;i<=m;i++)
        {
            for(j=1;j<=m;j++)
            {
                for(k=1;k<=m;k++)
                {
                    tmp[i][j]+=b[i][k]*c[k][j];
                    tmp[i][j]%=mod;
                }
            }
        }
        for(i=1;i<=m;i++)
        {
            for(j=1;j<=m;j++)
            a[i][j]=tmp[i][j];
        }
    }
    void build(int num)
    {
        if(num==1)
        return;
        build(num-1);
        init(c[num],c[num-1],c[num-1]);
    }
    LL abmodn(LL a,LL b,LL n)
    {
        LL d=1,i,bi[40],num=0;
        while(b>0)
        {
            bi[num++]=b%2;
            b/=2;
        }
        for(i=num-1;i>=0;i--)
        {
            d=(d*d)%n;
            if(bi[i])
            d=(a*d)%n;
        }
        return d;
    }
    void solve(int n,int a,int b)
    {
        memset(ans,0,sizeof(ans));
        int t[55],num=0;
        while(n)
        {
            t[++num]=n%2;
            n/=2;
        }
        build(num);
        int i,j;
        for(i=1;i<=m;i++)
        {
            for(j=1;j<=m;j++)
            ans[i][j]=c[num][i][j];
        }
        for(i=1;i<num;i++)
        {
            if(t[i])
            {
                init(ans,ans,c[i]);
            }
        }
        LL x=(ans[1][1]+ans[2][1])%mod,y=(ans[1][2]+ans[2][2])%mod;
        LL ANS=(abmodn(a,x,mod+1)*abmodn(b,y,mod+1))%(mod+1);
        printf("%I64d\n",ANS);
    }
    int main()
    {
       // freopen("dd.txt","r",stdin);
        c[1][1][1]=0;
        c[1][2][1]=c[1][1][2]=c[1][2][2]=1;
        int a,b,n;
        while(scanf("%d%d%d",&a,&b,&n)!=EOF)
        {
            if(n==0)
            printf("%d\n",a);
            else if(n==1)
            printf("%d\n",b);
            else if(n==2)
            printf("%I64d\n",(LL)a*b%(mod+1));
            else
            {
                solve(n-2,a,b);
            }
        }
        return 0;
    }


  • 相关阅读:
    今天开始用 VSU 2010
    Visual Studio 2010 模型设计工具 基本应用
    Asp.Net访问Oracle 数据库 执行SQL语句和调用存储过程
    Enterprise Library 4.1 Security Block 快速使用图文笔记
    解决“System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本。”(图)
    一个Oracle存储过程示例
    Enterprise Library 4.1 Application Settings 快速使用图文笔记
    Oracle 10g for Windows 简体中文版的安装过程
    Oracle 11g for Windows 简体中文版的安装过程
    Oracle 9i 数据库 创建数据库 Net 配置 创建表 SQL查询 创建存储过程 (图)
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3087228.html
Copyright © 2011-2022 走看看