形态形成场(矩阵乘法优化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的个数。

#include <cctype>
#include <cstdio>
#include <cstring>
using namespace std; typedef long long LL;
const int maxk=30, maxn=40, maxl=105;
int n, r, k, zero[maxn];
char s[maxk][maxl];
struct Mat{
int g[maxn][maxn];
}matrix[maxn], C;
void up(int &x, int y){ x+=y-r; x=(x<0?x+r:x); }
Mat& operator *(const Mat &A, const Mat &B){
memset(C.g, 0, sizeof(C.g));
for (int i=0; i<=n+1; ++i)
for (int j=0; j<=n+1; ++j)
for (int k=0; k<=n+1; ++k)
up(C.g[i][j], 1ll*A.g[i][k]*B.g[k][j]%r);
return C;
} void build(int id){ //复合字符'A'+i 所对应的转移矩阵
int len=strlen(s[id]), num;
Mat &now=matrix[id], trans;
for (int i=0; i<=n+1; ++i) now.g[i][i]=1; //相当于直接让转移矩阵相乘
for (int i=3; i<len; ++i){
if (isdigit(s[id][i])){
num=s[id][i]-'0';
memset(trans.g, 0, sizeof(trans.g));
trans.g[0][n]=trans.g[n][n]=trans.g[n+1][n+1]=1;
for (int j=0; j<n; ++j) trans.g[j][(j*10+num)%n]=1;
if (num) trans.g[n+1][num%n]=1;
else up(zero[id], 1);
now=now*trans;
} else {
num=s[id][i]-'A';
now=now*matrix[num];
up(zero[id], zero[num]);
}
}
} int main(){
scanf("%d%d%d", &n, &r, &k);
for (int i=0; i<k; ++i) scanf("%s", s[i]);
for (int i=k-1; ~i; --i) build(i);
int ans=zero[0]; up(ans, matrix[0].g[n+1][0]);
up(ans, matrix[0].g[n+1][n]);
printf("%d\n", ans);
return 0;
}

形态形成场(矩阵乘法优化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. 机器学习:PCA(基础理解、降维理解)

    PCA(Principal Component Analysis) 一.指导思想 降维是实现数据优化的手段,主成分分析(PCA)是实现降维的手段: 降维是在训练算法模型前对数据集进行处理,会丢失信息. ...

  2. 查看,修改ceph节点的ceph配置命令

    标签(空格分隔): ceph,ceph运维,ceph配置 查看ceph配置 1. 查看ceph默认配置: # ceph --show-config 2. 查看 type.num 的ceph默认配置: ...

  3. 第十五章 深入分析iBatis框架之系统架构与映射原理(待续)

    iBatis框架主要的类层次结构 iBatis框架的设计策略 iBatis框架的运行原理 iBatis框架对SQL语句的解析 数据库字段映射到Java对象 示例运行的结果 设计模式解析之简单工厂模式 ...

  4. 生产环境该如何选择lvs的工作模式,和哪一种算法

    lvs的工作模式有这几种: 1.RR : 轮叫算法,平均分配,你一个,我一个: 2.WRR :加权轮叫算法,谁的处理能力强,谁的权重就高: 3.LC :最少链接算法,谁的连接数最少,谁就处理更多的链接 ...

  5. Solaris11 How-To

    允许root用户使用ftp - 修改/etc/ftpd/ftpusers文件,移除或注释掉"root" - 修改/etc/proftpd.conf文件,"RootLogi ...

  6. Log4j 记录error 日志

    第一个bug的起始,是在线上日志发现一个频繁打印的异常——java.lang.ArrayIndexOutOfBoundsException.但是却没有堆栈,只有一行一行的ArrayIndexOutOf ...

  7. DDD学习笔录——领域驱动设计DDD概念总结

  8. 问题:sqlserver 跨服务器连接;结果:Sql Server 跨服务器连接

    Sql Server 跨服务器连接 用openrowset连接远程SQL或插入数据 --如果只是临时访问,可以直接用openrowset --查询示例 select * from openrowset ...

  9. DAY9-python并发之多线程理论

    一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合 ...

  10. JS中,关于数组的练习题

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...