~~~题面~~~

题解:

一开始看觉得很难,理解了之后其实还挺容易的。

首先我们考虑朴素DP:

  令f[i][j]表示长串到了第i项, 与不吉利数字(模式串)匹配到了第j项的方案。

  显然ans = f[n][0] + f[n][1] + …… + f[n][m-1];

  可以肉眼看出f[1][0] = 9, f[1][1] = 1;

  于是我们考虑如何转移。

  首先我们观察到,f[i-1][j]如果要给f[i][k]做贡献,那么就要使得匹配到j位变成匹配到k位。

  我们设g[j][k]表示原本是匹配到j位,加入一个新数字后变成匹配到k位的方案数。这里的匹配到x位的x是指匹配到模式串的第x位。

  那么我们有转移方程:$f[i][j] = \sum_{i=0}^{m-1}f[i-1][k]*g[k][j]$

  那么如何求解g[i][j]呢?

  可以考虑KMP。但是由于数据比较小,所以这里就直接用暴力了。

  首先我们枚举i表示当前已经匹配到了第i位(i可以为0)

  然后我们枚举新加进来的数

  再我们再枚举可能会匹配 l 位,从高位开始枚举,

  然后暴力检验看是不是可以刚好匹配到 l 位,注意要从后面开始匹配,如果没解释清楚,看代码就知道了。

  如果可以刚好匹配到 l 位,那么我们就++g[i][l]并break

然后我们考虑优化:

  观察转移方程$f[i][k] = \sum_{i=0}^{m-1}f[i-1][j]*g[j][k]$.

  emmmm,..与矩阵相乘完美吻合。。。。

  所以用矩阵加速一下就好啦

 

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 23
int n, m, p, ans;
char s[AC], tmp[AC];
struct matrix{
int s[AC][AC];
}f, g, box; void pre()
{
scanf("%d%d%d", &n, &m, &p);
scanf("%s", s + );
if(n == )
{
if(m == ) ans = ;
else ans = ;
ans %= p;
printf("%d\n", ans);
exit();
}
//g.s[0][1] = 1, g.s[0][0] = 9;//因为g是匹配数,所以行也可能是0
for(R i = ; i < m ; i++)//枚举已经匹配到了哪一位
{
tmp[i] = s[i];
for(R j = ; j <= ; j++)//枚举下一位是什么
{
tmp[i + ] = j + '';
int t, k = ;
for(R l = i + ; l >= ; l--)//枚举最多可以匹配几位
{
t = l, k = i + ;
while(s[t] == tmp[k] && t) --t, --k;
if(!t)
{
if(l != m) ++g.s[i][l];
break;
} }
}
}
} void build()
{
f.s[][] = , f.s[][] = ;
} void cal1()
{
for(R j = ; j < m; j++)//枚举是第一行的第几列,注意0也是合法的
{
box.s[][j] = ;
for(R l = ; l < m; l++)//枚举f的对应行和g的对应列
box.s[][j] += f.s[][l] * g.s[l][j];
box.s[][j] %= p;
}
f = box;
} void cal2()
{
for(R i = ; i < m; i++)
for(R j = ; j < m; j++)
{
box.s[i][j] = ;
for(R l = ; l < m; l++)
box.s[i][j] += g.s[i][l] * g.s[l][j];
box.s[i][j] %= p;
}
g = box;
} void qpow(int have)
{
while(have)
{
if(have & ) cal1();
cal2();
have >>= ;
}
} void work()
{
for(R i = ; i < m; i++) ans += f.s[][i];
ans %= p;
printf("%d\n", ans);
} int main()
{
freopen("in.in", "r", stdin);
pre();
build();
qpow(n - );
work();
fclose(stdin);
return ;
}

 

[HNOI2008]GT考试 矩阵优化DP的更多相关文章

  1. bzoj1009 [HNOI2008] GT考试 矩阵乘法+dp+kmp

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4542  Solved: 2815[Submit][Statu ...

  2. 矩阵优化dp

    链接:https://www.luogu.org/problemnew/show/P1939 题解: 矩阵优化dp模板题 搞清楚矩阵是怎么乘的构造一下矩阵就很简单了 代码: #include < ...

  3. bzoj 3120 矩阵优化DP

    我的第一道需要程序建矩阵的矩阵优化DP. 题目可以将不同的p分开处理. 对于p==0 || p==1 直接是0或1 对于p>1,就要DP了.这里以p==3为例: 设dp[i][s1][s2][r ...

  4. HDU - 2294: Pendant(矩阵优化DP&前缀和)

    On Saint Valentine's Day, Alex imagined to present a special pendant to his girl friend made by K ki ...

  5. [六省联考2017]组合数问题 (矩阵优化$dp$)

    题目链接 Solution 矩阵优化 \(dp\). 题中给出的式子的意思就是: 求 nk 个物品中选出 mod k 为 r 的个数的物品的方案数. 考虑朴素 \(dp\) ,定义状态 \(f[i][ ...

  6. bzoj 1009 [HNOI2008]GT考试——kmp+矩阵优化dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 首先想到 确保模式串不出现 就是 确保每个位置的后缀不是该模式串. 为了dp,需要记录 ...

  7. 洛谷P3193 GT考试 kmp+矩阵优化dp

    题意 求\(N\)位数字序列(可以有前导0)中不出现某\(M\)位子串的个数,模\(K\). \(N<=10^9,M<=20,K<=1000\) 分析 设\(dp[i][j]\)表示 ...

  8. BZOJ1009 [HNOI2008]GT考试 矩阵

    去博客园看该题解 题目 [bzoj1009][HNOI2008]GT考试 Description 阿申准备报名参加GT考试,准考证号为N位数X1X2….Xn(0<=Xi<=9),他不希望准 ...

  9. [Sdoi2017]序列计数 矩阵优化dp

    题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4818 思路 先考虑没有质数限制 dp是在同余系下的,所以\(f[i][j]\)表示前i个点, ...

随机推荐

  1. NavRouter

    使用方法只需要跟vue-router一样正常使用即可,这里我们新加了一个路由跳转方法nav: router.nav()//参数同router.replace一样. 路由跳转策略 首先说下路由跳转过程, ...

  2. mysql5.6 无法远程连接问题解决

    需要配置mysql5.6版本的my.cnf文件,我的my.cnf文件配置如下: port=3306是我后来自己加上的.加上这个之后重启mysql service mysqld restart 记得给r ...

  3. requests,lxml爬启信宝

    首先, 添加requests模块: 然后, 添加lxml模块: 启信宝登录抓包: QiXinBao.py: import requestsfrom lxml import etree loginUrl ...

  4. Unity热更新文件的服务器部署(IIS)

    1.VS新建一个"ASP.NET空网站" 工程结构如下 最好设置.Net FrameWork版本为 V4.0或者V4.5版本的,因为我们的程序最后是要部署到阿里云的虚拟服务器上的, ...

  5. mysql bin log配置及查看

    mysql执行sql可以通过设置mysql bin 日志进行记录查看   mysql bin日志配置如下:   log_bin:on log_bin_basename:bin文件路径及名前缀(/var ...

  6. 拓扑排序 (Ordering Tasks UVA - 10305)

    题目描述: 原题:https://vjudge.net/problem/UVA-10305 题目思路: 1.依旧是DFS 2.用邻接矩阵实现图 3.需要判断是否有环 AC代码 #include < ...

  7. 从零开始的Python学习Episode 4——列表

    一.列表 列表与数组相似,定义一个列表 a=[1,2,3,4,5] 1.基本操作 a=[1,2,3,4] #切片 范围取值时,包括第一项但不包括最后一项,顾头不顾尾 print(a[0:]) #从头到 ...

  8. Python3 数据类型-字典

    字典是一种可变数据类型,且可存储任意类型对象. 字典使用大括号"{}"括起来,由键(key)和值(values)组成,键只能使用不可变类型定义,值可以使用可变类型{'键':'值'} ...

  9. C语言特殊符号

    -> ->在C语言中称为间接引用运算符,是二目运算符,优先级同成员运算符“.”.用法:p->a,其中p是指向一个结构体的指针,a是这个结构体类型的一个成员.表达式p->a引用了 ...

  10. IT启示录

    引用电影<夏洛特烦恼>中夏洛的一句话:"一直以来,我根本就不知道自己想要什么".可以说在写这篇博客之前我仍然没有考虑清楚之后的道路,即使早已明确了走游戏开发的道理,却不 ...