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 ...
随机推荐
- 使用Sophus练习李群SO3、SE3以及对应的李代数so3、se3
这是高博<视觉SLAM14讲,从理论到实践>第4章的练习.加了一些注释和理解: #include <iostream>#include <cmath>using n ...
- 洛谷——P2659 美丽的序列
P2659 美丽的序列 单调栈维护区间最小值,单调递增栈维护区间最小值, 考虑当前数对答案的贡献,不断加入数,如果加入的数$>$栈顶,说明栈顶的元素对当前数所在区间是有贡献的,同时加入当前的数. ...
- UVA - 11536 Smallest Sub-Array(尺取法)
题目: 思路: 读完题之后第一时间想到的是尺取法来做这个题,结果让自己写写崩了,还是练得少!! 到网上搜了一下学习了大佬的标记方法,用一个变量来判断是不是都已经出现,要比每次都判断一下快超多. 代码: ...
- Radar Installation POJ - 1328 (贪心)
题目大意(vj上的翻译版本) 假定海岸线是无限长的直线.陆地位于海岸线的一侧,海洋位于另一侧.每个小岛是位于海洋中的一个点.对于任何一个雷达的安装 (均位于海岸线上),只能覆盖 d 距离,因此海洋中的 ...
- oracle的分号、斜杠和commit
;分号表示一个语句的结束 //表示执行前面的一个代码块,例如begin/end,代码块后面必须跟/才能执行. commitcommit表示提交一个事务,例如insert,delete,update等, ...
- Hadoop Mapreduce 中的Partitioner
Partitioner的作用的对Mapper产生的中间结果进行分片,以便将同一分组的数据交给同一个Reduce处理,Partitioner直接影响Reduce阶段的负载均衡. MapReduce提供了 ...
- AWK简单使用方法
1. 命令格式 gawk [OPTIONS] 'program' FILES.... program:'PATTERN{ACTION}' 一条awk命令中,PATTERN和ACTION,至少存在一个才 ...
- 《hello-world》第八次团队作业:Alpha冲刺
项目 内容 这个作业属于哪个课程 2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十二 团队作业8:软件测试与Alpha冲刺 团队名称 <hello--worl ...
- 【Codeforces 264B】Good Sequences
[链接] 我是链接,点我呀:) [题意] 让你在一个递增数组中选择一个最长子序列使得gcd(a[i],a[i+1])>1 [题解] 设f[i]表示以一个"含有素因子i的数字" ...
- JavaSE 学习笔记之IO流(二十二)
IO流:用于处理设备上数据. 流:可以理解数据的流动,就是一个数据流.IO流最终要以对象来体现,对象都存在IO包中. 流也进行分类: 1:输入流(读)和输出流(写). 2:因为处理的数据不同,分为字节 ...