题意:

求长度为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. redis 为什么是单线程,为什么速度快。

    redis 5中存储方式 String.List.Set.Hash.ZSet这5种 数据库的工作模式按存储方式可分为: 硬盘数据库和内存数据库.Redis 将数据储存在内存里面,读写数据的时候都不会受 ...

  2. iOS - 点击背景视图收起系统键盘

    我们在 IOS 开发中经常会需要在输入框输入数据后,需要收起系统键盘,比如由于手机屏幕不是很大,可能由于输入信息后,系统键盘就会遮挡住下一步的按钮,而系统键盘有没有收起键,所以我们可以实现点击背景视图 ...

  3. POJ 1269 Intersecting Lines(判断两直线位置关系)

    题目传送门:POJ 1269 Intersecting Lines Description We all know that a pair of distinct points on a plane ...

  4. Freemarker 的基础使用 (一)

    以下内容来自:http://www.oschina.net/p/freemarker FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写. FreeMarker ...

  5. 重新认识C语言的指针(上)

    ​ 独创性并不是首次观察某种新事物,而是把旧的.很早就是已知的,或者是人人都视而不见的事物当新事物观察,这才证明是有真正的独创头脑 -尼采 本文已经收录至我的GitHub,欢迎大家踊跃star 和 i ...

  6. Prometheus+Alertmanager+Grafana监控组件容器部署

    直接上部署配置文件 docker-compose.yml version: '3' networks: monitor: driver: bridge services: prometheus: im ...

  7. 解析Json字符串中的指定的值

    { "head": { ", "Id": "20191008144448iAQE", "Message": & ...

  8. isStatic:检测数据是不是除了symbol外的原始数据

    function isStatic(value) { return( typeof value === 'string' || typeof value === 'number' || typeof ...

  9. js css html加载顺序

    1.js放在head中会立即执行,阻塞后续的资源下载与执行.因为js有可能会修改dom,如果不阻塞后续的资源下载,dom的操作顺序不可控.正常的网页加载流程是这样的.浏览器一边下载HTML网页,一边开 ...

  10. python3文件操作

    文件操作的过程 1)打开 2)操作 3)关闭 1.写(清空写入) # f = open(file='test', mode='w', encoding='utf-8') # 第一种情况 # f.wri ...