题意:

求长度为n的不含长为m的指定子串的字符串的个数

1s, n<=1e9, m<=50

思路:

长见识了。。

设那个指定子串为s

f[i][j]表示长度为i的字符串(其中后j个字符与s的前j个字符一致的情况下)的方法数

若匹配到s串长度为i的后缀加一个字符num可以组成最长长度为j的后缀,设a[i][j]为num的方法数

例如,s为12312,a为

9 1 0 0 0 0
8 1 1 0 0 0
8 1 0 1 0 0
9 0 0 0 1 0
8 1 0 0 0 1

(i,j都是从0到m-1)

如a[1][2]表示从“1”到“12”可以加的字符方法数,显然加“2”才可以,所以a[1][2]=1

而a[2][0]表示从“12”到“”可以加的字符方法数:显然不能加“3”,不然s串会匹配到"123";也不能加“1”,不然s串会匹配成"1"。所以a[2][0]=8

求a矩阵的方法是kmp,感觉只可意会(我写不出来QAQ)

显然f[i][x]只能由f[i-1][k]转移而来,而k为多少,要看a数组了

然后状态转移方程为:$f[i][j] = f[i-1][0]*a[0][j]+f[i-1][1]*a[1][j] +\dots + f[i-1][m-1]*a[m-1][j]$

这个状态转移方程可以用矩阵快速幂来加速

答案就是$\sum f[n][i]$

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional> #define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) using namespace std; typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL; const db eps = 1e-;
//const int mod = 1e9+7;
const int maxn = 2e3+;
const int maxm = 2e6+;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0); int a[][];
int f[][];
int n, m, mod;
char s[maxn];
int Next[maxn]; void mtpl(int a[][], int b[][], int s[][]){
int tmp[][];
for(int i = ; i < m; i++){
for(int j = ; j < m; j++){
tmp[i][j] = ;
for(int k = ; k < m; k++){
tmp[i][j]+=a[i][k]*b[k][j]%mod;
tmp[i][j]%=mod;
}
}
}
for(int i = ; i < m; i++){
for(int j = ; j < m; j++){
s[i][j] = tmp[i][j];
}
}
return;
} void fp(int x){
while(x){
if(x&)mtpl(f,a,f);
mtpl(a,a,a);
x>>=;
}
return;
} void kmp(){
int fix = ;
for(int i = ; i <= m; i++){
while(fix && s[fix+]!=s[i])fix=Next[fix];
if(s[fix+]==s[i])++fix;
Next[i]=fix;
} for(int i = ; i < m; i++){
for(char j = ''; j <= ''; j++){
fix = i;
while(fix&&s[fix+]!=j)fix=Next[fix];
if(j==s[fix+])a[i][fix+]++;
else a[i][]++;
}
}
return;
} int main(){
scanf("%d %d %d", &n, &m, &mod);
scanf("%s", s+);
mem(a, );
kmp();
mem(f,);
f[][]=;
fp(n);
int ans = ;
for(int i = ; i < m; i++){
ans += f[][i];
ans%=mod;
}
printf("%d", ans);
return ;
}
/*
5
3 4 5 1 2
*/

BZOJ 1009 [HNOI2008]GT考试(矩阵快速幂优化DP+KMP)的更多相关文章

  1. 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...

  2. 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 ...

  3. 2018.10.22 bzoj1009: [HNOI2008]GT考试(kmp+矩阵快速幂优化dp)

    传送门 f[i][j]f[i][j]f[i][j]表示从状态"匹配了前i位"转移到"匹配了前j位"的方案数. 这个东西单次是可以通过跳kmp的fail数组得到的 ...

  4. 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个 ...

  5. 省选模拟赛 Problem 3. count (矩阵快速幂优化DP)

    Discription DarrellDarrellDarrell 在思考一道计算题. 给你一个尺寸为 1×N1 × N1×N 的长条,你可以在上面切很多刀,要求竖直地切并且且完后每块的长度都是整数. ...

  6. bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串计数DP问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我... 首 ...

  7. BZOJ 1009 [HNOI2008]GT考试 ——矩阵乘法 KMP

    先用KMP处理所有的转移,或者直接暴力也可以. 然后矩阵快速幂即可. #include <cstdio> #include <cstring> #include <ios ...

  8. 2019.02.11 bzoj4818: [Sdoi2017]序列计数(矩阵快速幂优化dp)

    传送门 题意简述:问有多少长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数,且其中至少有一个数是质数,答案对201704082017040820170408取模(n≤1e9, ...

  9. 2018.11.08 NOIP模拟 景点(倍增+矩阵快速幂优化dp)

    传送门 首先按照题意构造出转移矩阵. 然后可以矩阵快速幂求出答案. 但是直接做是O(n3qlogm)O(n^3qlogm)O(n3qlogm)的会TTT掉. 观察要求的东西发现我们只关系一行的答案. ...

随机推荐

  1. 从0开发3D引擎(六):函数式反应式编程及其在引擎中的应用

    目录 上一篇博文 介绍函数式反应式编程 函数式反应式编程学习资料 函数式反应式编程的优点与缺点 优点 缺点 异步处理的其它方法 为什么使用Most库 引擎中相关的函数式反应式编程知识点 参考资料 大家 ...

  2. Netty快速入门(09)channel组件介绍

    书接上回,继续介绍组件. ChannelHandler组件介绍 ChannelHandler组件包含了业务处理核心逻辑,是由用户自定义的内容,开发人员百分之九十的代码都是ChannelHandler. ...

  3. 洛谷 UVA11021 Tribles

    UVA11021 Tribles 题意翻译 题目大意 一开始有kk种生物,这种生物只能活1天,死的时候有p_ipi​的概率产生ii只这种生物(也只能活一天),询问m天内所有生物都死的概率(包括m天前死 ...

  4. numpy基本知识

    """np.arrayobject 数组或嵌套的数列dtype 数组元素的数据类型,可选copy 对象是否需要复制,可选order 创建数组的样式,C为行方向,F为列方向 ...

  5. 史上最简单的vi教程,10分钟包教会

    从第一次接触vi/vim到现在已经十几年了,在这个过程中,来来回回,反反复复,学习vi很多次了. 虽然关于vi的使用,我还远未达到"专家"的水平,但对于vi的使用,我有话说. 1. ...

  6. Ubuntu 设置中文输入法

    环境:新安装的Ubuntu 16.04 LTS 本来打算使用sogou拼音,但是在输入后的提示框中内容为乱码,因此尝试重新安装. 1.sudo apt-get remove sogoupinyin & ...

  7. git工作中总结2

    目的:在远程分支上添加新文件(代码) 1.clone分支 git clone -b 分支 url cd到文件夹,添加文件到改目录下 2.创建新的分支并切换 git checkout -b dev(本地 ...

  8. MySQL多表联查以及以及架构

    多表之间关联查询:      据库操作中,多表联合查询是后台开发者常用到的查询语句. JOIN SQL JOIN 子句用于把来自两个或多个表的行结合起来,最常见的 JOIN 类型:SQL INNER ...

  9. php代码没解析成功

    在Apache中加载PHP模块 1.打开Apache的配置文件httpd.conf(位于Apache2\conf 目录下). 2.查找 “#LoadModule ssl_module modules/ ...

  10. [bzoj3991] [洛谷P3320] [SDOI2015] 寻宝游戏

    Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有 \(N\) 个村庄和 \(N-1\) 条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬 ...