hdu4291 A Short problem(矩阵快速幂+循环节)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4291

题目意思:求g(g(g(n))) mod 109 + 7,其中g(n) = 3g(n - 1) + g(n - 2),g(1) = 1,g(0) = 0。

思路:一个很简单的矩阵快速幂,简单的想法就是先用n算出g(n),然后再算g(g(n)),然后再算最外层,都是mod(1e9+7),这么做就错了,这道题有一个循环节的问题,看来这种嵌套的递推式取mod是存在循环节的,以后要注意下。

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

#define ll long long
const int N = 2;

ll n;
struct Matrix{
    ll mat[N][N];
    ll MOD;
    Matrix operator*(const Matrix& m)const{
          Matrix tmp;
          tmp.MOD = MOD;
          for(int i = 0 ; i < N ; i++){
              for(int j = 0 ; j < N ; j++){
                  tmp.mat[i][j] = 0;
                  for(int k = 0; k < N ; k++)
                      tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%MOD;
                  tmp.mat[i][j] %= MOD;
              }
          }
          return tmp;
    }
};

ll Pow(Matrix m , ll x , ll MOD){
    if(x <= 1) return x;
    Matrix ans;
    ans.MOD = m.MOD = MOD;
    ans.mat[0][0] = ans.mat[1][1] = 1;
    ans.mat[1][0] = ans.mat[0][1] = 0;
    x--;
    while(x){
        if(x%2)
            ans = ans*m;
        x /= 2;
        m = m*m;
    }
    return ans.mat[0][0]%MOD;
}

int main(){
    ll L1 = 1e9+7;
    ll L2 = 222222224;
    ll L3 = 183120;
    Matrix m;
    m.mat[0][0] = 3; m.mat[1][1] = 0;
    m.mat[0][1] = 1; m.mat[1][0] = 1;
    while(scanf("%lld" , &n) != EOF){
         ll x = Pow(m , n , L3);
         ll y = Pow(m , x , L2);
         ll ans = Pow(m , y , L1);
         printf("%lld\n" , ans);
    }
    return 0;
}

 

posted @ 2018-09-26 21:28  Somnus、M  阅读(163)  评论(0编辑  收藏  举报