HDU 4291 A Short problem(矩陣快速冪+迴圈節)

bigbigship發表於2015-04-07

題目連結“:

http://acm.hdu.edu.cn/showproblem.php?pid=4291


題意:

g(0)=0,g(1)=1;

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

求g(g(g(n))) mod 109 + 7


分析:

首先我們得認識到,如果一層一層算是必定會超時的。

其次,取模運算是有迴圈節的。

step1我們找出g(x)%1000000007的迴圈節 mod1

step2 設g(g(n)) = g(x) x=g(n) 對mod1 取模得到mod2.

剩下的工作就是進行三次的快速冪運算 從內到外進行。

程式碼如下:

#include <iostream>
#include <cstdio>
using namespace std;

typedef long long LL;

const LL mod = 1e9+7;

const LL mod1 = 222222224;

const LL mod2 = 183120;

//´ò±íÕÒÑ­»·½Ú
//mod 1e9+7 ===> mod1 ,mod mod1 ===>mod2;
/*
int main()
{
    LL f0=0,f1=1;
    for(LL i=1;;i++){
        LL tmp = (3 * f1 + f0)%mod;
        f0 = f1 ;
        f1 = tmp;
        if(f0==0&&f1==1){
            printf("ans: %d\n",i);
            break;
        }
    }
    return 0;
}
*/

struct matrix{
    LL a[2][2];
};

matrix I={
    1,0,
    0,1
};

matrix multi(matrix A,matrix B,int mod){
    matrix C;
    for(int i=0;i<2;i++){
        for(int j = 0; j < 2;j++){
            C.a[i][j]=0;
            for(int k=0;k<2;k++)
                C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
        }
    }
    return C;
}

LL pow(matrix A ,LL n,LL mod){
    matrix tmp = I;
    while(n){
        if(n&1)
            tmp= multi(tmp,A,mod);
        n>>=1;
        A=multi(A,A,mod);
    }
    return tmp.a[0][0];
}

int main(){
    LL n;
    while(~scanf("%lld",&n)){
        matrix A= {
            3,1,
            1,0
        };
        if(n>=2) n = pow(A,n-1,mod2);
        if(n>=2) n = pow(A,n-1,mod1);
        if(n>=2) n = pow(A,n-1,mod);
        printf("%I64d\n",n);
    }
    return 0;
}














相關文章