HDU-4291 A Short problem(矩阵快速幂)

来源:互联网 发布:opengl游戏编程 pdf 编辑:程序博客网 时间:2024/05/21 06:52

A Short problem

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


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
012
 

Sample Output
0142837

题解:矩阵快速幂

由于g(n)是嵌套形成g(g(g(n)))的,只有最外层才mod 1e9+7,因此不能每一层都mod 1e9+7
我们可以先找到最外层在mod 1e9+7下的循环节p,然后再找第二层在mod p下的循环节p1

这样答案就等于g(g(g(n)%p1)%p)%mod

#include<cstdio>#include<algorithm>#include<string.h>#include<map>using namespace std;typedef long long LL;struct Mat{    LL x[2][2],sz;    LL mod;    Mat(){        memset(x,0,sizeof(x));        sz=2;    }    void init(){        for(int i=0;i<sz;i++) x[i][i]=1;    }    Mat operator*(const Mat& m)const{        Mat ret;        ret.mod=mod;        for(int i=0;i<sz;i++)            for(int j=0;j<sz;j++)                for(int k=0;k<sz;k++)                    ret.x[i][j]=(ret.x[i][j]+x[i][k]*m.x[k][j])%mod;        return ret;    }    void print(){        for(int i=0;i<sz;i++)            for(int j=0;j<sz;j++)                printf("%d%c",x[i][j],j==sz-1?'\n':' ');    }};Mat pow(Mat A,LL k,LL mod){    Mat ret;    ret.init();    ret.mod=A.mod=mod;    //printf("[%lld]\n",mod);    while(k){        if(k&1) ret=ret*A;        A=A*A;        k>>=1;    }    return ret;}LL get_ans(LL k,LL p){    if(k<=0) return 0;    Mat A;    A.x[0][0]=3;A.x[0][1]=1;    A.x[1][0]=1;    return pow(A,k-1,p).x[0][0];}const LL mod1 = 1e9 + 7;const LL mod2=222222224;const LL mod3=183120;LL solve(LL k){    k=get_ans(k,mod3);    k=get_ans(k,mod2);    return get_ans(k,mod1);}int main(){    LL n;    //freopen("in.txt","r",stdin);    while(~scanf("%lld",&n)){        printf("%lld\n",solve(n));    }    return 0;}


阅读全文
0 0