首页 > 其他分享 >OJ周赛第一场——连环画

OJ周赛第一场——连环画

时间:2022-10-31 15:36:10浏览次数:51  
标签:周赛 OJ 连环画 int 矩阵 单词 trie 拼接 dp

连环画  

问题描述

连环画是一种特殊类型的填字游戏。

小马和小亮最近迷上了这个游戏。他们一共有n个不同的单词,每个单词有无限个。

他们很好奇如果各自拿若干个单词拼接成一个长为m的单词,有多少种方法能够使得两人拼接的单词相同。

他们可能不太聪明,所以请聪明的你来解决这个问题。

(如果对于任意两种方法,这两种方法中小马或小亮拿的单词不一样,则被认为是不同的。)

由于这个数字可能相当大,所以输出它的模数998244353。

 

输入 

第一行包含两个整数n和m(1≤n≤8,1≤m≤10^9)-- 他们拥有的不同的单词数和需要拼接成的单词的长度。

接下来的n行中的每一行都包含一个词--一个不超过5个小写拉丁字母的非空字符串。所有的词都是保证不同。 

输出

打印一个整数--给定的不同实例的数量对998244353取模。

 

输入例子 1         输出例子 1

3 5
ababa              11
ab a

输入例子 2         输出例子 2

2 4
ab                4
cd







输入例子 3         输出例子 3

5 100
a
aa
aaa             142528942
aaaa
aaaaa

提示

下面是对第一个例子的解释

image.png

字母上方的红线表示小马所拼接的单词,字母下方的蓝线表示小亮所拼接的单词。

 

先不考虑m的长度。

对于所有字母,我们可以考虑建出trie树。Trie上最多有40个节点。

然后设出dp[i][j][k]表示总共拼接出长为i,小马拼出的第i个字符为trie上的第j的节点,小亮拼出的为第k个节点

得出转移式dp[i][a][b]=sum(dp[i-1][c][d])

特别的a,b分别为c,d的孩子,a所在trie上的字符等于b,c等于d。

我们还忽略掉了如何结束该单词,那么如果a点可以为一个单词的结尾,那么可以考虑转移到根节点上(根节点为1),即dp[i][1][b]=sum(dp[i-1][c][d]),同理b也要考虑。

但是m很大不能直接转移。

我们可以将dp后两维离散化成点,理论上有40*40个点,但是发现被转移的点条件比较苛刻,所以所有合法的状态不超过40*5个。

那么我们可以按照往年的惯例(bushi,对i这维矩阵快速幂。

通过dfs可以生成转移矩阵。

 

//by kexyfa
#include<bits/stdc++.h>
using namespace std;

const int P=998244353,N=170;
typedef array<array<int,N>,N> T; //定义矩阵
T w; //转移矩阵
int m,sz;
int f[N][26],  //存储trie信息
    g[N][N],  //对于两人所在树上节点[a][b]关于矩阵的映射
    ed[N];
T mul(T &a,T &b){
    T c;
    fill(&c[1][1],&c[m][m],0); //清空矩阵
    for (int i=1;i<=m;++i)
     for (int k=1;k<=m;++k)
      for (int j=1;j<=m;++j)
        c[i][j] = (1LL*a[i][k]*b[k][j] + c[i][j])%P;
    return c;
}

int dfs(int a,int b){
    auto &t=g[a][b];
    if (t) return t;
    t=g[b][a]=++m;
    for (int i=0;i<26;++i){
        int x=f[a][i],y=f[b][i];
        if (x&&y){
            w[t][dfs(x,y)]++;  //直接转移
            if (ed[x]) w[t][dfs(0,y)]++; //以x点为单词结尾
            if (ed[y]) w[t][dfs(0,x)]++; //以y点为单词结尾
            if (ed[x] &&ed[y]) w[t][dfs(0,0)]++; //两人一同结尾
        }
    }
    return t;
}
void solve(){
    int n,q;cin>>n>>q;
    
    for (int i=0;i<n;++i){
        string s;cin>>s;
        
        int p=0;
        for (char c:s){
            auto&t=f[p][c-'a'];
            if (!t)  t=++sz;
            p=t;
        } //建立trie树
        
        ed[p]=1;  //标识有单词在p点结束
    }

    dfs(0,0); // 构造转移矩阵
    
    T r;
    fill(&r[1][1],&r[m][m],0);
    r[1][1]=1;
    
    for (;q;q>>=1,w=mul(w,w))    //矩阵快速幂
     if (q&1) r=mul(r,w);
    cout<<r[1][1];
}

int main(){
    solve();
    return 0-0;
}

 

标签:周赛,OJ,连环画,int,矩阵,单词,trie,拼接,dp
From: https://www.cnblogs.com/hihopkc/p/16844466.html

相关文章

  • OJ周赛第一次——Good morning
    Goodmorning 问题描述一天,小马在A点过B分准时起床(24小时制),而小亮在C点过D分1秒准时起床。 输入 输入4个整数A,B,C,D0≤A≤230≤B≤590≤C≤230≤D≤5......
  • OJ周赛第一场——数列
    数列 问题描述给你一个长度为N的由0和1组成的整数序列:A=(A1,A2,⋯,AN​)。你可以选择是否进行一个操作。该操作为选择一个区间(l,r),使得区间的0变成1,1变成0。......
  • 树上连通有关背包:【BZOJ4182】shopping &【HDU6566】The Hanged Man
    选这两道题是因为这两道题都是树上背包,而且选的点的要求都与连通性有关,而且都是按dfs序DP来模拟不断加入物品,而且都能用树剖和点分治优化(不过优化的点一个跟子树大小有......
  • 2022年zzuli周赛(2)
    消消乐我们可以考虑贪心,想一想,如果\(s\)串和\(t\)串中有一个字母相同的话,是不是就相当于必然存在\(S,t\)相同(将两个字符串删减成一个字母就可以了)C:#include<stdio......
  • cryptoJs DES_CBC_Pkcs7 转成 Java
    前端DES加密:importcryptoJsfrom'crypto-js';//DES加密functionencrypt(message,key,iv){//字符串转16进制constkeyHex=cryptoJs.enc.Utf8.parse......
  • LeeCode 317周赛复盘
    T1:可被3整数的偶数的平均值思路:数组遍历被3整数的偶数\(\Leftrightarrow\)被6整数的数publicintaverageValue(int[]nums){intsum=0;intcount=0;......
  • leetcode 第90场双周赛
    6226.摧毁一系列目标题意:对于数组中每一个数nums[i],可以摧毁数组中值等于nums[i]+c*space的数(c为非负整数),求摧毁最大数量时的最小nums[i]思路:如果两个数x,y可以同时被摧......
  • 【XSY3434】【UOJ431】time map(线段树维护位运算)
    首先注意到一个性质:如果我们把权值相同且相邻的点归为一个连通块的话,那么一个叶子节点往上会经过至多\(O(\logV)\)个连通块(因为父亲节点一定是儿子节点的子集)。又注意......
  • 【XSY2444】【BZOJ4042】【CERC2014】【luogu4757】Parades(树形dp+状压dp)
    题面Description从前有个A国,它有\(n\)个城市和\(n-1\)条道路。每条路连接两个城市。城市之间两两可达。每个城市与不超过10条道路相连。现在给出\(m\)条路径,要求从这些......
  • 【XSY1976】【BZOJ2286】【SDOI2011】消耗战(虚树,dp)
    这题的dp思想还是比较容易想的,关键是如何保证时间复杂度,这时就用到了虚树的技巧。1.虚树是什么?(虚树的性质)不妨设现在询问给出了\(k\)个点,我们命名这些节点为关键节点。......