hdoj 4291 A Short problem 【找循环节 + 矩阵快速幂】



A Short problem

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


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 <= 10 18), You should solve for 
g(g(g(n))) mod 10 9 + 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
 



题意不说了。。。


思路:打表找出每一层循环节,然后矩阵快速幂。


打表找循环节代码:

#include <cstdio>
#define LL long long
#define MOD1 1000000007
#define MOD2 222222224
#define MOD3 183120
int main()
{
    LL x = 0, y = 1;
    for(int i = 1; ; i++)
    {
        LL x1 = 3*y%MOD2 + x;
        x1 %= MOD2;
        x = y, y = x1;
        if(x == 0 && y == 1)
        {
            printf("%d\n", i);
            break;
        }
    }
    return 0;
}





AC代码:


#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define MOD1 1000000007
#define MOD2 222222224
#define MOD3 183120
using namespace std;
struct Matrix
{
    LL a[3][3];
};
Matrix ori, res;
void init()
{
    memset(ori.a, 0, sizeof(ori.a));
    memset(res.a, 0, sizeof(res.a));
    ori.a[0][1] = ori.a[1][0] = 1;
    ori.a[1][1] = 3;
    for(int i = 0; i < 2; i++)
        res.a[i][i] = 1;
}
Matrix muitl(Matrix x, Matrix y, LL M)
{
    Matrix z;
    memset(z.a, 0, sizeof(z.a));
    for(int i = 0; i < 2; i++)
    {
        for(int k = 0; k < 2; k++)
        {
            if(x.a[i][k] == 0) continue;
            for(int j = 0; j < 2; j++)
                z.a[i][j] = (z.a[i][j] + (x.a[i][k] * y.a[k][j]) % M) % M;
        }
    }
    return z;
}
LL ans, F[3];
LL solve(LL n, LL M)
{
    if(n <= 1)
        return n;
    init();
    n -= 1;//自减一
    while(n)
    {
        if(n & 1)
            res = muitl(ori, res, M);
        ori = muitl(ori, ori, M);
        n >>= 1;
    }
    return F[1] * res.a[1][1] % M;
}
int main()
{
    F[0] = 0, F[1] = 1;
    LL N;
    while(scanf("%lld", &N) != EOF)
    {
        ans = solve(N, MOD3);//最里层
        ans = solve(ans, MOD2);//第二层
        ans = solve(ans, MOD1);//最外层
        printf("%lld\n", ans);
    }
    return 0;
}




你可能感兴趣的:(hdoj 4291 A Short problem 【找循环节 + 矩阵快速幂】)