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;
    }


  • 相关阅读:
    EL&Filter&Listener:EL表达式和JSTL,Servlet规范中的过滤器,Servlet规范中的监听器,观察着设计模式,监听器的使用,综合案例学生管理系统
    Node搭建api接口
    菜鸟程序员的react TodoList练习之旅
    js 手机靓号正则
    js 去除省市区
    select 下拉框在手机上第一次点击获取不到值
    ios下输入框聚焦文字显示不出来
    浅谈js中的深浅拷贝
    原型和原型链
    将多个对象合并成一个数组的方法
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3087228.html
Copyright © 2011-2022 走看看