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 ...
随机推荐
- 07Oracle Database 数据表
Oracle Database 数据表 DDL 数据定义语言 - 建立数据库对象 create /alter/ drop/ truncate 创建表 Create table table_name( ...
- 04Microsoft SQL Server 数据库创建,查看,使用,修改及删除
Microsoft SQL Server 数据库创建,查看,使用,修改及删除 创建数据库 创建普通数据库 USE [master] GO CREATE DATABASE [MyDataBase] -- ...
- go new() 和 make() 的区别
看起来二者没有什么区别,都在堆上分配内存,但是它们的行为不同,适用于不同的类型. new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种方法 返回一个指向类型为 ...
- C++ string使用
在c语言里,我们使用一个字符串时,是通过字符数组或者字符指针的方式来进行使用,在C++里,标准模板库已经给我们提供了string类型(string是以类的方式提供给我们使用). 定义和初始化strin ...
- 暴力搜索+散列--P1008 三连击
题目描述 将1,2, ⋯,9共9个数分成3组,分别组成3个三位数,且使这3个三位数构成1:2:3的比例,试求出所有满足条件的3个三位数. 输入输出格式 输入格式: 木有输入 输出格式: 若干行,每行3 ...
- Django DTL模板语法中的过滤器
template_filter_demo 过滤器相关: 一.形式:小写{{ name | lower }} 二.串联:先转义文本到HTML,再转换每行到 <p> 标签{{ my_text| ...
- 常量Constant
常量通常指的是一个固定的值,例如:1.2.3.’a’.’b’.true.false.”helloWorld”等. 在Java语言中,主要是利用关键字final来定义一个常量. 常量一旦被初始化后不能再 ...
- 【Codeforces 300C】Beautiful Numbers
[链接] 我是链接,点我呀:) [题意] 让你找到长度为n的数字 这个数字只由a或者b组成 且这n个数码的和也是由a或者b组成的 求出满足这样要求的数字的个数 [题解] 枚举答案数字中b的个数为y,那 ...
- @requestbody---接受前端传json对象并绑定javabean
@requestbody---接受前端传json对象并绑定javabean----https://blog.csdn.net/ljxbbss/article/details/74452326 最近代码 ...
- noip模拟赛 abcd
[问题描述]有4个长度为N的数组a,b,c,d.现在需要你选择N个数构成数组e,数组e满足a[i]≤e[i]≤b[i]以及 并且使得 最大.[输入格式]输入文件名为abcd.in.输入文件共 N+1 ...