bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009
字符串计数DP问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我...
首先要设计一个不太好想的状态:f[i][j]表示大串上到第 i 位时有小串前 j 位的后缀,且不包含整个小串的方案数;
也就是如果小串是 12312 , f[5][3] 表示目前大串的情况是 **123... ;
这个状态要从 i 转移到 i+1 ,还需要一个帮助它的数组 a,a[i][j]表示在长度为 i 的后缀后面加一个数字能变成长度为 j 的后缀的方案数;
也就是说,对于 12312,从0到4的 a 数组应该如下:
9 1 0 0 0
8 1 1 0 0
8 1 0 1 0
9 0 0 0 1
8 1 0 0 0
a 数组的定义可以联想到 kmp 算法,事实上它就是通过 kmp 算法的 nxt 数组求得;
于是就可以得到转移方程:f[i][j] = ∑(0<=k<m) f[i-1][k] * a[k][j]
然后发现对于每一步,进行的转移都是相同的;
所以可以用矩阵快速幂来优化,转移矩阵就是 a 数组;
看了好多好多博客才明白...
这篇博客写得很好:https://blog.csdn.net/loi_dqs/article/details/50897662
尤其是代码真的简洁!所以模仿着写了。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int n,m,mod,nxt[],sum;
char s[];
struct Matrix{
int n,m,a[][];
Matrix(int x=,int y=):n(x),m(y) {memset(a,,sizeof a);}
void init()
{
for(int i=;i<n;i++)a[i][i]=;//0 ~ n-1
}
Matrix operator * (const Matrix &y) const
{
Matrix x(n,y.m);
for(int i=;i<n;i++)//从0到n-1
for(int k=;k<m;k++)
for(int j=;j<y.m;j++)
(x.a[i][j]+=(ll)a[i][k]*y.a[k][j]%mod)%=mod;
return x;
}
};
void getnxt()
{
nxt[]=nxt[]=;//第0位有字符,但含义是无匹配
for(int i=;i<m;i++)
{
// int k=i;
int k=nxt[i];
while(s[i]!=s[k]&&k)k=nxt[k];
nxt[i+]=(s[i]==s[k])?k+:;//前一位的nxt冒进一位,对应下面从0开始的字符串匹配
}
}
Matrix pw(Matrix x,int k)
{
Matrix ret(x.n,x.m); ret.init();
for(;k;k>>=,x=x*x)
if(k&)ret=ret*x;
return ret;
}
int main()
{
scanf("%d%d%d%s",&n,&m,&mod,&s);
getnxt();
Matrix f(m,m);
for(int i=;i<m;i++)
for(int j='';j<='';j++)//第i位上填j
{
int k=i;//已经有长度为i的前缀,而k对应字符串上i的后一位
while(k&&s[k]!=j)k=nxt[k];//冒进一位的nxt,表示给i后一位进行匹配
if(s[k]==j)k++;//匹配到了第k位,也就是有了k+1长度的前缀
if(k!=m)f.a[i][k]++;
}
Matrix fn=pw(f,n);
Matrix ans(,m);
ans.a[][]=; ans=ans*fn;
for(int i=;i<m;i++)
(sum+=ans.a[][i])%=mod;
printf("%d",sum);
return ;
}
bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP的更多相关文章
- [bzoj1009](HNOI2008)GT考试 (kmp+矩阵快速幂加速递推)
Description 阿 申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学 A1A2...Am(0&l ...
- 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...
- 2018.10.22 bzoj1009: [HNOI2008]GT考试(kmp+矩阵快速幂优化dp)
传送门 f[i][j]f[i][j]f[i][j]表示从状态"匹配了前i位"转移到"匹配了前j位"的方案数. 这个东西单次是可以通过跳kmp的fail数组得到的 ...
- BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4266 Solved: 2616[Submit][Statu ...
- 2018.10.23 bzoj1297: [SCOI2009]迷路(矩阵快速幂优化dp)
传送门 矩阵快速幂优化dp简单题. 考虑状态转移方程: f[time][u]=∑f[time−1][v]f[time][u]=\sum f[time-1][v]f[time][u]=∑f[time−1 ...
- 2018.10.16 uoj#340. 【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂优化dp)
传送门 一道不错的矩阵快速幂优化dpdpdp. 设f[i][j][k][l]f[i][j][k][l]f[i][j][k][l]表示前iii轮第iii轮还有jjj个一滴血的,kkk个两滴血的,lll个 ...
- 省选模拟赛 Problem 3. count (矩阵快速幂优化DP)
Discription DarrellDarrellDarrell 在思考一道计算题. 给你一个尺寸为 1×N1 × N1×N 的长条,你可以在上面切很多刀,要求竖直地切并且且完后每块的长度都是整数. ...
- [HNOI2008][bzoj1009] GT考试 [KMP+矩阵快速幂]
题面 传送门 思路 首先,如果$n$和$m$没有那么大的话,有一个非常显然的dp做法: 设$dp[i][j]$表示长度为i的字符串,最后j个可以匹配模板串前j位的情况数 那么显然,答案就是$\sum_ ...
- BZOJ 1009 [HNOI2008]GT考试(矩阵快速幂优化DP+KMP)
题意: 求长度为n的不含长为m的指定子串的字符串的个数 1s, n<=1e9, m<=50 思路: 长见识了.. 设那个指定子串为s f[i][j]表示长度为i的字符串(其中后j个字符与s ...
随机推荐
- Could not resolve type alias 'map '. Cause: java.lang.ClassNotFoundException: Cannot find class: map
把resultType改为resultMap, 把parameterType改为parameterMap,重新发布并运行.
- vue-router + axios token登录状态认证
vue项目中登录状态判断往往基于jwt认证,我们可以采用判断本地是否存在token,及token是否过期或token值错误 1.利用vue-router 钩子函数判断本地是否存在token impor ...
- mysql 转载
一.MySQL概述 1.什么是数据库 ? 答:数据的仓库,如:在ATM的示例中我们创建了一个 db 目录,称其为数据库 2.什么是 MySQL.Oracle.SQLite.Access.MS SQL ...
- MyBatis 的基本介绍及使用
一.简介 MyBatis 是支持定制化 SQL.存储过程以及高级映射的持久层框架(ORM).MyBatis 可以使用简单的 XML 或 注解用于配置和映射数据表,是将 POJO(Plain Old ...
- java8 foreach不能使用break、countinue
在学习1.8新特性的过程中,发现foreach中不可以使用break和countinue,然后我使用了return,结果如下图,对循环并没有影响. 百度一下,发现了一个不一样的回答 然后我就看了下源码 ...
- (2) GoJS Node简介
node GoJS提供了非常简单的创建Node节点的方法,可将文本内容.结点形状.背景颜色.边距等属性通过数据绑定[go.Binding]直接绑定到对应的Node数据中. 本文简单介绍Node的创建过 ...
- clipboard.js兼容ios
再使用clipboard.js做项目时,项目需求是在非input,button等可以点击的标签(span,p,div)上实现点击来复制内容,在PC端和移动端android没问题,但是到了ios毫无反应 ...
- unigui的ini文件读写【6】
procedure THeaderFooterForm.writerParas; var IniFile : TIniFile; begin try IniFile:=TIniFile.Create( ...
- 什么是js严格模式?
[03] 严格模式 ECMAScript 5 引入了严格模式(strict mode)的概念.严格模式是为JavaScript 定义了一种不同的解析与执行模型.在严格模式下,ECMAScript 3 ...
- 【Codeforces 490C】Hacking Cypher
[链接] 我是链接,点我呀:) [题意] 让你把一个字符串分成左右两个部分 形成两个正数 使得这两个正数一个能被a整除,一个能被b整除 找到任意一个解就可以 [题解] 枚举分割的断点i 枚举的时候用同 ...