• HDU——4291A Short problem(矩阵快速幂+循环节)


    A Short problem

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2461    Accepted Submission(s): 864


    Problem Description
      According to a research, VIM users tend to have shorter fingers, compared with Emacs users.
      Hence they prefer problems short, too. Here is a short one:
      Given n (1 <= n <= 1018), You should solve for 
    g(g(g(n))) mod 109 + 7

      where
    g(n) = 3g(n - 1) + g(n - 2)

    g(1) = 1

    g(0) = 0
     
    Input
      There are several test cases. For each test case there is an integer n in a single line.
      Please process until EOF (End Of File).
     
    Output
      For each test case, please print a single line with a integer, the corresponding answer to this case.
     
    Sample Input
    0 1 2
     
    Sample Output
    0 1 42837
     
    三层复合函数。写完交上去TLE,不解。查了题解发现有循环节。循环节的话用set::find函数来查找是否存在过,若存在则输出循环节,不存在则插入当前数值继续循环。
    然后就是矩阵快速幂了。递推式:递推式(当某一层n为0的时候加上mod否则可能出错)
    代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<sstream>
    #include<cstring>
    #include<cstdio>
    #include<string>
    #include<deque>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long LL;
    #define INF 0x3f3f3f3f
    const long long mod=1000000007;
    struct mat
    {
        LL pos[2][2];
        mat(){memset(pos,0,sizeof(pos));}
    };
    inline mat mul(const mat &a,const mat &b,const LL &mod)
    {
        mat c;
        for (int i=0; i<2; i++)
        {
            for (int j=0; j<2; j++)
            {
                for (int k=0; k<2; k++)
                {
                    c.pos[i][j]+=((a.pos[i][k])%mod*(b.pos[k][j])%mod)%(mod);
                }
            }
        }
        return c;
    }
    inline mat matpow(mat a,LL b,const LL &mod)
    {
        mat r;
        r.pos[1][1]=r.pos[0][0]=1;
        mat bas=a;
        while (b!=0)
        {
            if(b&1)
                r=mul(r,bas,mod);
            bas=mul(bas,bas,mod);
            b>>=1;
        }
        return r;
    }
    int main(void)
    {
        mat one,t;
        LL n,ans;
        one.pos[0][0]=1;
        one.pos[0][1]=0;        
        t.pos[0][0]=3;
        t.pos[0][1]=t.pos[1][0]=1;
        mat poww,initt;
        while (cin>>n)
        {
            if(n==0)
            {
                cout<<"0"<<endl;
                continue;
            }
            poww=t,initt=one;
            poww=matpow(poww,n-1,183120);
            initt=mul(initt,poww,183120);        
            ans=initt.pos[0][0];
            ans+=183120;
    		        
            poww=t,initt=one;
            poww=matpow(poww,ans-1,222222224);
            initt=mul(initt,poww,222222224);        
            ans=initt.pos[0][0];
            ans+=222222224;
    		        
            poww=t,initt=one;        
            poww=matpow(poww,ans-1,1000000007);
            initt=mul(initt,poww,1000000007);
            cout<<initt.pos[0][0]%1000000007<<endl;
        }
        return 0;
    }
  • 相关阅读:
    技巧和诀窍;在VS 2005里优化ASP.NET 2.0Web项目的Build性能(转)
    去噪:用于验证码图片识别的类续(C#代码)
    快速申请QQ号码的技巧(图文介绍)
    vs2005中调试js
    "Take the Internet Back“挂机程序(读信息挣美元)
    javascript的编写、调试
    硬盘速度和Visual Studio性能
    Java Swing的DragAndDrop机制
    Rails 的 SNS 准备
    学习,编译ffmpeg tutorial
  • 原文地址:https://www.cnblogs.com/Blackops/p/5468297.html
Copyright © 2020-2023  润新知