zoukankan      html  css  js  c++  java
  • hdu 2842 Chinese Rings 矩阵快速幂

    分析:

    后面的环能不能取下来与前面的环有关,前面的环不被后面的环所影响。所以先取最后面的环

    设状态F(n)表示n个环全部取下来的最少步数

    先取第n个环,就得使1~n-2个环属于被取下来的状态,第n-1个环属于未被取下来的状态。那么F(n) = F(n-2) + 1 + ... (这里的1表示取下第n个需要一步)

    即F(n)可以为F(n-2) + 1与某些数的和。取下n后,1~n-2为取下的状态,n-1为未被取下的状态。如果我们想取下n-1,那么n-2要为未被取下来的状态且1~n-3为被取下的状态。

    但是这里不能直接将n-2变成为未取下的状态,你想把n-2的状态改变,就得使n-3为未被取下来的状态且1~n-4为被取下的状态;你想把n-3的状态改变,就得使n-4为未被取下来的状态且1~n-5为被取下的状态.

    这个一直递推下去你要使1~n-2全部属于未被取下的状态才能继续取n-1。

    将1~n全部取下来有下列四步

    第一步:取1~n-2,需要F(n-2)步

    第二步:取第n个,需要1步

    第三步:恢复1~n-2,需要F(n-2)步 (取下来的最少步数和恢复的最少步数是一样的,它们是对称的)

    第四步:将1~n-1个全部取下来

    所以:F(n) = F(n-1) + 2*F(n-2) + 1

    矩阵快速幂套模板啦!

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    const int Mod = 200907;
    const int N = 5;
    int msize;
    
    struct Mat
    {
        int mat[N][N];
    };
    
    Mat operator *(Mat a, Mat b)
    {
        Mat c;
        memset(c.mat, 0, sizeof(c.mat));
        for(int k = 0; k < msize; ++k)
            for(int i = 0; i < msize; ++i)
                if(a.mat[i][k])
                    for(int j = 0; j < msize; ++j)
                        if(b.mat[k][j])
                            c.mat[i][j] = ((ll)a.mat[i][k] * b.mat[k][j] + c.mat[i][j])%Mod;
        return c;
    }
    
    Mat operator ^(Mat a, int k)
    {
        Mat c;
        memset(c.mat,0,sizeof(c.mat));
        for(int i = 0; i < msize; ++i)
            c.mat[i][i]=1;
        for(; k; k >>= 1)
        {
            if(k&1) c = c*a;
            a = a*a;
        }
        return c;
    }
    
    int main()
    {
        int n;
        msize = 3;
        Mat A;
        A.mat[0][0] = 1, A.mat[0][1] = 2, A.mat[0][2] = 1;
        A.mat[1][0] = 1, A.mat[1][1] = 0, A.mat[1][2] = 0;
        A.mat[2][0] = 0, A.mat[2][1] = 0, A.mat[2][2] = 1;
        while(~scanf("%d",&n) && n)
        {
            if(n==1)
            {
                puts("1");
                continue;
            }
            Mat ans = A^(n-2);
            printf("%d
    ", (ans.mat[0][0]*2 + ans.mat[0][1] + ans.mat[0][2])%Mod);
        }
        return 0;
    }
  • 相关阅读:
    luogu P1833 樱花 看成混合背包
    luogu P1077 摆花 基础记数dp
    luogu P1095 守望者的逃离 经典dp
    Even Subset Sum Problem CodeForces
    Maximum White Subtree CodeForces
    Sleeping Schedule CodeForces
    Bombs CodeForces
    病毒侵袭持续中 HDU
    病毒侵袭 HDU
    Educational Codeforces Round 35 (Rated for Div. 2)
  • 原文地址:https://www.cnblogs.com/pach/p/7256925.html
Copyright © 2011-2022 走看看