题意:

求长度为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. JPA或Hibernate中使用原生SQL实现分页查询、排序

    发生背景:前端展示的数据需要来自A表和D表拼接,A表和D表根据A表的主键进行关联,D表的非主键字段关联C表的主键,根据条件筛选出符合的数据,并且根据A表的主键关联B表的主键(多主键)的条件,过滤A表中 ...

  2. spring同时操作多数据库 多个mysql和mongoDB,不需切换数据源,同时操作mysql和mongodb

    源码:https://github.com/haihai1172/spring-mysql-mongoDB 项目目录 1.环境搭建,java-sdk 1.8 具体怎么搭建,就不说了 2.配置jdbc. ...

  3. vue 项目路由跳转后显示不同的title

    1.在router/index.js的每个路由中配置title 2.在项目中运行命令 npm install vue-wechat-title --save 安装插件(在 package.json文件 ...

  4. dp - 逆序数序列

    对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆序对数为k的这样自然数数 ...

  5. 元素定位工具Weditor的使用

    (1).安装:pip install --pre --upgrade weditor 安装成功 (2).启动python -m weditor

  6. Flask蓝图(Blueprint)

    一.作用 1.目录结构划分 2.url添加前缀 url_prefix 3.应用特殊装饰器,在该蓝图定义的特殊装饰器,只在改蓝图的起效 二.简单示例 1.创建一个项目文件 2.创建一个同名的python ...

  7. python类属性和实例属性(类变量和实例变量)

    在类中,根据变量定义的位置不同,以及定义的方式不同,类属性又可以细分为以下三种类型: 类体中,所有函数之外:类属性(类变量) 类体中,所有函数内部,以"self.变量名"的方式定义 ...

  8. CQBZOJ 【重庆市NOIP模拟赛】避难向导

    题目描述 "特大新闻,特大新闻!全国爆发了一种极其可怕的病毒,已经开始在各个城市 中传播开来!全国陷入了巨大的危机!大量居民陷入恐慌,想要逃到其它城市以 避难!经调查显示,该病毒来自于C 市 ...

  9. Ubuntu下makefile的简单使用

    在Windows下,只需要简单的点击以下make,rebuild即可.而在Linux下,这样的IDE环境并没有提供,难道必须每一步都执行一遍吗?比较ok的做法自然是能够利用批处理脚本来进行操作了,这样 ...

  10. Java 8 Stream流编程学习

    本文是自己学习菜鸟教程中总结的笔记,用于快速找代码,完整的文档见菜鸟教程:Java 8 Stream Stream 使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达 ...