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

来源:互联网 发布:windows ce6.0模拟器 编辑:程序博客网 时间:2024/05/17 09:13



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 <= 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
 



题意不说了。。。


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


打表找循环节代码:

#include <cstdio>#define LL long long#define MOD1 1000000007#define MOD2 222222224#define MOD3 183120int 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 183120using 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;}


0 0