zoukankan      html  css  js  c++  java
  • C

    HDU - 2604

    我们可以通过在一串序列的末尾不断添加'(f)'或是'(m)'来获得所有的串,其中我们要及时去除不合法的串'(fff)','(fwf)'

    首先把所有的串分类,按照最末尾两个字符分四类,分别是,'(ff)','(fm)','(mf)','(mm)'

    分别用(a_1),(a_2),(a_3),(a_4)来表示每种类别对应串的数量。

    [ left[ egin{array}{ccc} a_1\\ a_2\\ a_3\\ a_4\\ end{array} ight] * left[ egin{array}{ccc} 1 & 0 & 1 & 0\\ 1 & 0 & 1 & 0\\ 0 & 1 & 0 & 1\\ 0 & 1 & 0 & 1\\ end{array} ight] left[ egin{array}{ccc} a'_1\\ a'_2\\ a'_3\\ a'_4\\ end{array} ight] ]

    注意,上面的式子是包括所有的转移的,其中有两种不合法的转移未删去。下面是最终转移。

    [ left[ egin{array}{ccc} a_1\\ a_2\\ a_3\\ a_4\\ end{array} ight] * left[ egin{array}{ccc} 0 & 0 & 1 & 0\\ 1 & 0 & 1 & 0\\ 0 & 0 & 0 & 1\\ 0 & 1 & 0 & 1\\ end{array} ight] left[ egin{array}{ccc} a'_1\\ a'_2\\ a'_3\\ a'_4\\ end{array} ight] ]

    答案等于([1,1,1,1] *) 转移矩阵 得到的([ans_1,ans_2,ans_3,ans_4]),四个数相加即可

    
    #include<bits/stdc++.h>
    using namespace std;
    
    int l,mod;
    
    struct jz{
        int g[10][10];
        void init(){
            memset(g,0,sizeof(g));
        }
        void one(){
            memset(g,0,sizeof(g));
            for(int i = 1; i <= 4; ++ i) g[i][i] = 1;
        }
    };
    jz operator * (jz a, jz b){
        jz c; c.init();
        for(int i = 1; i <= 4; ++ i) 
        for(int j = 1; j <= 4; ++ j)
        for(int k = 1; k <= 4; ++ k)
        c.g[i][j] += a.g[i][k] * b.g[k][j] % mod, c.g[i][j] %= mod;
        return c;
    }
    jz ksm(jz x,int y){
        jz z; z.one();
        while(y){
            if(y & 1) z = z * x;
            y >>= 1;
            x = x * x;
        }
        return z;
    }
    
    int qpow(int x,int y){
        int z = 1;
        while(y){
            if(y & 1) z = 1ll * z * x % mod;
            y >>= 1;
            x = 1ll * x * x % mod;
        }
        return z;
    }
    
    jz a;
    
    int main(){
        while(scanf("%d%d",&l,&mod) != EOF){
            a.init();
            a.g[1][4] = 1;
            a.g[2][1] = a.g[2][4] = 1;
            a.g[3][2] = a.g[3][3] = 1;
            a.g[4][3] = 1;
            //a.g[5][1] = a.g[5][2] = a.g[5][5] = 1;
            
            if(l <= 2) { printf("%d
    ",qpow(2,l)); continue; }
            
            l -= 2;
            a = ksm(a,l);
            
            int ans = 0;
            for(int i = 1; i <= 4; ++ i)
            for(int j = 1; j <= 4; ++ j)
            ans += a.g[i][j] , ans %= mod;
            
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    /*
    a1 ff     0001     ff
    b1 fm     1001     fm
    a2 mm     0110     mm
    b2 mf     0010     mf
    */
    
    
  • 相关阅读:
    洛谷1098 字符串的展开 解题报告
    洛谷1086 花生采摘 解题报告
    洛谷1125 笨小猴 解题报告
    洛谷1056 排座椅 解题报告
    洛谷1067 多项式输出 解题报告
    洛谷1003 铺地毯 解题报告
    JS在不同js文件中互相调用
    JS鼠标滚轮事件
    JS闭包
    PHP中header('content-type:text/html;charset="utf-8')和error_reporting()的作用
  • 原文地址:https://www.cnblogs.com/zzhzzh123/p/13355673.html
Copyright © 2011-2022 走看看