C – Queuing

HDU - 2604

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

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

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

\[
\left[
\begin{array}{ccc}
a_1\\\\
a_2\\\\
a_3\\\\
a_4\\\\
\end{array}
\right]

*

\left[
\begin{array}{ccc}

1 & 0 & 1 & 0\\\\
1 & 0 & 1 & 0\\\\
0 & 1 & 0 & 1\\\\
0 & 1 & 0 & 1\\\\

\end{array}
\right]

\left[
\begin{array}{ccc}
a'_1\\\\
a'_2\\\\
a'_3\\\\
a'_4\\\\
\end{array}
\right]

\]

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

\[
\left[
\begin{array}{ccc}
a_1\\\\
a_2\\\\
a_3\\\\
a_4\\\\
\end{array}
\right]

*

\left[
\begin{array}{ccc}

0 & 0 & 1 & 0\\\\
1 & 0 & 1 & 0\\\\
0 & 0 & 0 & 1\\\\
0 & 1 & 0 & 1\\\\

\end{array}
\right]

\left[
\begin{array}{ccc}
a'_1\\\\
a'_2\\\\
a'_3\\\\
a'_4\\\\
\end{array}
\right]

\]

答案等于\([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\n",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\n",ans);
    }
    return 0;
}

/*
a1 ff     0001     ff
b1 fm     1001     fm
a2 mm     0110     mm
b2 mf     0010     mf
*/

原文链接: https://www.cnblogs.com/zzhzzh123/p/13355673.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C - Queuing

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/369390

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午6:55
下一篇 2023年3月2日 下午6:56

相关推荐