形态形成场(矩阵乘法优化dp)

短信中将会涉及前\(k\)种大写字母,每个大写字母都有一个对应的替换式\(Si\),替换式中只会出现大写字母和数字,比如\(A→BB,B→CC0,C→123\),代表 \(A=12312301231230,B=1231230,C=123\)。现在对于给定的替换式,求字符 A 所代表的串有多少子串满足:

  • 这个子串为单个字符\(0\)或没有前导\(0\)。
  • 把这个子串看作一个十进制数后模\(n\)等于\(0\)。

答案对\(r\)取模。对于100%的数据,$2 \leq r \leq 10^9; 1 \leq k \leq 26; 4 \leq \left| S_i \right| \leq 100 $。

首先可以想出一个暴力dp:\(f[i][j]\)表示到第i位时,模n为j的串的个数,那么显然\(f[i][(10j+s[i])\%n]+=f[i-1][j]\)。复杂度是\(O(len\times n)\)。

但是这样只能拿60分,并不能过这道题。怎么办呢?观察一下题目,其实就是将一个字符的字符串展开以后dp,并且最多展开26层,同一个字符可能被展开多次。有没有想到矩阵优化dp?由于每次\(f[s[i]\%n]\)要加上1,因此不能用传统的矩阵递推数列,还必须在向量中加上一维常量1。为了方便,再在向量中加一维ans。向量长这样:

\((f_0, f_1, f_2,\dots,f_{n-1},ans,1)\)。

这样转移矩阵\(g[n+1][n+1]\)就可以被描述为:

\(\left [ \begin{matrix} & 第1列 & 第i列 & 第n列 & 第n+1列 \\第一行 & \dots & \dots & 1&0 \\ 第二行 & \dots & \dots & 0 & 0 \\ 第三行 & \dots & \dots & 0 & 0 \\ \dots \\ 第n行 & 0 & 0 & 1 & 0 \\ 第n+1行 & 0 & [s[i]=ch]*[ch!='0'] & 0 & 1\end{matrix} \right ]\)

先将矩阵进行处理,再把初始向量和矩阵相乘。\((0, 0, \dots,0, 1)*g[n+1][n+1]=(f_0, f_1, \dots,ans,1)\),答案就是\(f_0+ans\)。由于初始向量只有第n+1项是1,所以\(f_0+ans=g[n+1][0]+g[n+1][n]\)。

注意单个字符0不能被漏掉统计,因此需要记录串中的0的个数。

  1. #include <cctype>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. typedef long long LL;
  6. const int maxk=30, maxn=40, maxl=105;
  7. int n, r, k, zero[maxn];
  8. char s[maxk][maxl];
  9. struct Mat{
  10. int g[maxn][maxn];
  11. }matrix[maxn], C;
  12. void up(int &x, int y){ x+=y-r; x=(x<0?x+r:x); }
  13. Mat& operator *(const Mat &A, const Mat &B){
  14. memset(C.g, 0, sizeof(C.g));
  15. for (int i=0; i<=n+1; ++i)
  16. for (int j=0; j<=n+1; ++j)
  17. for (int k=0; k<=n+1; ++k)
  18. up(C.g[i][j], 1ll*A.g[i][k]*B.g[k][j]%r);
  19. return C;
  20. }
  21. void build(int id){ //复合字符'A'+i 所对应的转移矩阵
  22. int len=strlen(s[id]), num;
  23. Mat &now=matrix[id], trans;
  24. for (int i=0; i<=n+1; ++i) now.g[i][i]=1; //相当于直接让转移矩阵相乘
  25. for (int i=3; i<len; ++i){
  26. if (isdigit(s[id][i])){
  27. num=s[id][i]-'0';
  28. memset(trans.g, 0, sizeof(trans.g));
  29. trans.g[0][n]=trans.g[n][n]=trans.g[n+1][n+1]=1;
  30. for (int j=0; j<n; ++j) trans.g[j][(j*10+num)%n]=1;
  31. if (num) trans.g[n+1][num%n]=1;
  32. else up(zero[id], 1);
  33. now=now*trans;
  34. } else {
  35. num=s[id][i]-'A';
  36. now=now*matrix[num];
  37. up(zero[id], zero[num]);
  38. }
  39. }
  40. }
  41. int main(){
  42. scanf("%d%d%d", &n, &r, &k);
  43. for (int i=0; i<k; ++i) scanf("%s", s[i]);
  44. for (int i=k-1; ~i; --i) build(i);
  45. int ans=zero[0]; up(ans, matrix[0].g[n+1][0]);
  46. up(ans, matrix[0].g[n+1][n]);
  47. printf("%d\n", ans);
  48. return 0;
  49. }

形态形成场(矩阵乘法优化dp)的更多相关文章

  1. 斐波那契数列 矩阵乘法优化DP

    斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007​\),\(n\le 10^{18}​\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...

  2. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

  3. 矩阵乘法优化DP

    本文讲一下一些基本的矩阵优化DP的方法技巧. 定义三个矩阵A,B,C,其中行和列分别为$m\times n,n \times p,m\times p$,(其中行是从上往下数的,列是从左往右数的) $C ...

  4. 矩阵乘法优化DP复习

    前言 最近做毒瘤做多了--联赛难度的东西也该复习复习了. Warning:本文较长,难度分界线在"中场休息"部分,如果只想看普及难度的可以从第五部分直接到注意事项qwq 文中用(比 ...

  5. 51nod 1583 犯罪计划——矩阵乘法优化dp

    文泽想在埃及做案n次,并且想在最后不用得到惩罚.案件的被分成几种类型.比如说,案件A,当案件A被重复犯两次时,案件A将被认为不是犯罪案件,因此犯案人不用得到惩罚.也就是说,案件A被犯偶数次时,犯案人将 ...

  6. 【bzoj2476】战场的数目 矩阵乘法优化dp

    题目描述 (战场定义为对于最高的一列向两边都严格不增的“用积木搭成”的图形) 输入 输入文件最多包含25组测试数据,每个数据仅包含一行,有一个整数p(1<=p<=109),表示战场的图形周 ...

  7. 【矩阵乘法优化dp】[Codeforces 621E] Wet Shark and Blocks

    http://codeforces.com/problemset/problem/621/E E. Wet Shark and Blocks time limit per test 2 seconds ...

  8. luoguP2768: 珍珠项链(矩阵乘法优化DP)

    题意:有K种珍珠,每种N颗,求长度为1~N的项链,包含K种珍珠的项链种类数.N<=1e9, K<=30; 思路:矩阵快速幂,加个1累加前缀和即可. #include<bits/std ...

  9. bzoj 4870: [Shoi2017]组合数问题 [矩阵乘法优化dp]

    4870: [Shoi2017]组合数问题 题意:求 \[ \sum_{i=0}^{n-1} \binom{nk}{ik+r} \mod p \] \(n \le 10^9, 0\le r < ...

随机推荐

  1. java代码实现通讯录实例,我不知道这有什么用。,

    运行显示: Friend:zl,Address:武大樱花美Colleagues:蔡依林,Department:麻城市人民政府 题目: 1.任务描述 完善上面通讯录名片的例子. 2.技能要点 掌握类继承 ...

  2. Lib之过?Java反序列化漏洞通用利用分析

    转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...

  3. 批量删除osd的shell脚本

    cluster环境: # cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) # ceph -v ceph version 12. ...

  4. 配置docker中免密码SSH

    更换docker国内镜像,使用DaoCloud,特别快 编写Dockerfile文件 FROM ubuntu MAINTAINER ggzone xxx@live.com ENV REFRESHED_ ...

  5. PDM/CDM中进行搜索

    Option   Explicit ValidationMode   =   True InteractiveMode =   im_Batch Dim   mdl   '当前model '获取当前活 ...

  6. 信号量sem 的用法

    #include <semaphore.h> sem_t sem; sem_init(&sem, 0, 0); sem_post(&sem); sem_wait(& ...

  7. DAY9-python并发之多进程

    一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...

  8. PTA 估值一亿的AI核心代码

    题面 比赛时被模拟题打自闭了,本来以为是个比较麻烦的模拟,实际上只要会C++的regex不到40行就能把这个题过掉了(orz smz) regex是用来处理正则表达式,里面有个函数regex_repl ...

  9. cocos2dx中的Rapidjson

    1 Json基础 JSON 概念和特点: JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻量级的文本数据交换格式,类似 XML ...

  10. Spring_02 注入类型值、利用引用注入类型值、spring表达式、与类相关的注解、与依赖注入相关的注解、注解扫描

    注意:注入基本类型值在本质上就是依赖注入,而且是利用的set方式进行的依赖注入 1 注入基本类型的值 <property name="基本类型的成员变量名" value=&q ...