~~~题面~~~

题解:

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

首先我们考虑朴素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. 阿里云中linux 下svn服务器安装

    摘要: 安装步骤如下: 1.yum install subversion 2.输入rpm -ql subversion查看安装位置,如下图:   我们知道svn在bin目录下生成了几个二进制文件. 输 ...

  2. 制作一个App的完整流程是哪些

    APP开发流程其实并不复杂,但是对于客户来说,.一般移动APP开发都离不开UI设计师.前端开发.后端开发.测试专员.产品经理等,由于他们的工作性质都不一样,我们且先把APP软件开发项目分为三个阶段: ...

  3. 使用postman实现半自动化

    前些日子项目要上一个活动,其中有一个功能是幸运大转盘,用户可以随机抽奖,奖品有多种满减券及多种商品,但是奖品都是有抽中概率的,且有的商品还设置有库存,所以测试点便是测试抽奖的概率和库存.接下来拆分一下 ...

  4. git服务器搭建及eclipse使用git

    一.搭建git服务器 1.yum install git 2.新建用户linux用户git,管理git服务 useradd git passwd git 3.初始化git仓库 git init --b ...

  5. Android 简介

    一 Android起源 android: 机器人 android是google公司开发的基于Linux2.6的免费开源操作系统 2005 Google收购 Android Inc. 开始 Dalvik ...

  6. Objective-C 构造方法 分类 类的深入研究

    构造方法 1.对象创建的原理 new的拆分两部曲 Person *p = [Person alloc]; 分配内存(+alloc) Person *p = [p init]; 初始化(-init) 合 ...

  7. 【WXS数据类型】Boolean

    属性: 名称 值类型 说明 [Boolean].constructor [String] 返回值为“Boolean”,表示类型的结构字符串 方法: 原型:[Boolean].toString() 说明 ...

  8. JAVA基础学习之路(十)this关键字

    class Book { String name; int price; int num;//构造方法之间的互相调用解决了代码的重复问题,但是一定要留出口 public Book() { ,); } ...

  9. 腾讯地图和百度地图的PHP相互转换

    /** * 百度地图---->腾讯地图 * @param double $lat 纬度 * @param double $lng 经度 * @return array(); */ functio ...

  10. Vuejs 实现简易 todoList 功能 与 组件

    todoList 结合之前 Vuejs 基础与语法 使用 v-model 双向绑定 input 输入内容与数据 data 使用 @click 和 methods 关联事件 使用 v-for 进行数据循 ...