hdoj 2842 Chinese Rings 【递推 + 矩阵快速幂】



Chinese Rings

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


Problem Description
Dumbear likes to play the Chinese Rings (Baguenaudier). It’s a game played with nine rings on a bar. The rules of this game are very simple: At first, the nine rings are all on the bar.
The first ring can be taken off or taken on with one step.
If the first k rings are all off and the (k + 1)th ring is on, then the (k + 2)th ring can be taken off or taken on with one step. (0 ≤ k ≤ 7)

Now consider a game with N (N ≤ 1,000,000,000) rings on a bar, Dumbear wants to make all the rings off the bar with least steps. But Dumbear is very dumb, so he wants you to help him.
 

Input
Each line of the input file contains a number N indicates the number of the rings on the bar. The last line of the input file contains a number "0".
 

Output
For each line, output an integer S indicates the least steps. For the integers may be very large, output S mod 200907.
 

Sample Input
 
       
1 4 0
 

Sample Output
 
       
1 10
 


题意:用最少步骤解出N连环。取出第k个的条件是,前k-2个已被取出,第k-1个环仍在支架上(0<= k<=N-2)


思路:假设取出前N个环所需要的步骤为F(N)。

若要取出第N个环,则前N - 2个环要被取出,这样F(N-2) +1就取出了第N个环。现在只剩下第N-1环没被取出,我们只需要将前N-2环再套上去(套上去和取下来步骤一样,都为F(N - 2)),这样上面只剩下N-1个环,全部取下的方案数为F(N-1)。


得到公式——F(N) = F(n - 1) + 2 * F(N - 2) + 1; 


得到矩阵:


hdoj 2842 Chinese Rings 【递推 + 矩阵快速幂】_第1张图片



注意用long long。


AC代码:


#include 
#include 
#include 
#include 
#define MOD 200907
#define LL long long
using namespace std;
struct Matrix
{
    LL a[5][5];
};
Matrix ori, res;
void init()
{
    memset(ori.a, 0, sizeof(ori.a));
    memset(res.a, 0, sizeof(res.a));
    ori.a[0][0] = ori.a[0][3] = ori.a[2][1] = 1;
    ori.a[2][3] = 2;
    ori.a[3][2] = ori.a[3][3] = 1;
    for(int i = 0; i < 4; ++i)
        res.a[i][i] = 1;
}
Matrix muitl(Matrix x, Matrix y)
{
    Matrix z;
    memset(z.a, 0, sizeof(z.a));
    for(int i = 0; i < 4; i++)
    {
        for(int k = 0; k < 4; k++)
        {
            if(x.a[i][k] == 0) continue;
            for(int j = 0; j < 4; j++)
                z.a[i][j] = (z.a[i][j] + (x.a[i][k] * y.a[k][j]) % MOD) % MOD;
        }
    }
    return z;
}
LL F[5];
void solve(int n)
{
    while(n)
    {
        if(n & 1)
            res = muitl(ori, res);
        ori = muitl(ori, ori);
        n >>= 1;
    }
    LL ans = 0;
    for(int i = 0; i < 4; i++)
        ans = (ans + (res.a[i][3] * F[i]) % MOD) % MOD;
    printf("%lld\n", ans);
}
int main()
{
    int N;
    while(scanf("%d", &N), N)
    {
        F[0] = 1; F[1] = 1; F[2] = 2, F[3] = 5;
        if(N <= 3)
        {
            printf("%lld\n", F[N]);
            continue;
        }
        init();
        solve(N-3);
    }
    return 0;
}



你可能感兴趣的:(递归,矩阵)