【BZOJ1009】GT考试(KMP算法,矩阵快速幂,动态规划)

题面

BZOJ

题解

看到这个题目

化简一下题意

长度为\(n\)的,由\(0~9\)组成的字符串中

不含串\(s\)的串的数量有几个

很显然,如果组成的字符串和\(s\)串做\(KMP\)的匹配的话

是不能匹配到最后一位的

所以,我们想到一个很显然的方程

\(f[i][j]\)表示当前做了第\(i\)位,在\(s\)串中匹配到了第\(j\)位

每次枚举下一位放的数字

以及每一位的位置

相当于做\(KMP\)的匹配

然后进行转移

所以,我们可以写出一个暴力

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int f[2000][30];
int nt[30],n,m,K;
char s[30];
void Get_Next(char *s)
{
int l=strlen(s+1);
nt[1]=0;
for(int i=2;i<=l;++i)
{
int t=nt[i-1];
while(t&&s[i]!=s[t+1])t=nt[t];
if(s[i]==s[t+1])t+=1;
nt[i]=t;
}
}
int main()
{
n=read();m=read();K=read();
scanf("%s",s+1);
Get_Next(s);
f[0][0]=1;
for(int i=0;i<n;++i)
{
for(int j='0';j<='9';++j)
{
for(int k=0;k<m;++k)
{
int t=k;
while(t&&s[t+1]!=j)t=nt[t];
if(j==s[t+1])t++;
(f[i+1][t]+=f[i][k])%=K;
}
}
}
int ans=0;
for(int i=0;i<m;++i)ans+=f[n][i];
printf("%d\n",ans%K);
return 0;
}

\(n\)的范围有\(10^9\)

不可能是\(O(n)\)解了

我们发现每次匹配的转移关系是一定的

所以可以用矩阵快速幂来优化\(dp\)转移

复杂度为\(O(n+m^3logn)\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int nt[30],n,m,K;
char s[30];
void Get_Next(char *s)
{
int l=strlen(s+1);
nt[1]=0;
for(int i=2;i<=l;++i)
{
int t=nt[i-1];
while(t&&s[i]!=s[t+1])t=nt[t];
if(s[i]==s[t+1])t+=1;
nt[i]=t;
}
}
struct Dalao
{
int s[30][30];
void init()
{
memset(s,0,sizeof(s));
for(int i=0;i<m;++i)s[i][i]=1;
}
void clear(){memset(s,0,sizeof(s));}
}G;
Dalao operator*(Dalao a,Dalao b)
{
Dalao ret;ret.clear();
for(int i=0;i<m;++i)
for(int j=0;j<m;++j)
for(int k=0;k<m;++k)
(ret.s[i][j]+=a.s[i][k]*b.s[k][j]%K)%=K;
return ret;
}
Dalao fpow(Dalao a,int b)
{
Dalao s;s.init();
while(b){if(b&1)s=s*a;a=a*a;b>>=1;}
return s;
}
int main()
{
n=read();m=read();K=read();
scanf("%s",s+1);
Get_Next(s);
for(int j='0';j<='9';++j)
{
for(int k=0;k<m;++k)
{
int t=k;
while(t&&s[t+1]!=j)t=nt[t];
if(j==s[t+1])t++;
G.s[k][t]++;
}
}
G=fpow(G,n);
int ans=0;
for(int i=0;i<m;++i)ans=(ans+G.s[0][i])%K;
printf("%d\n",ans%K);
return 0;
}

【BZOJ1009】GT考试(KMP算法,矩阵快速幂,动态规划)的更多相关文章

  1. [BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂)

    [BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂) 题面 阿申准备报名参加GT考试,准考证号为N位数X1X2-.Xn,他不希望准考证号上出现不吉利的数字.他的不吉利数学A ...

  2. BZOJ.1009.[HNOI2008]GT考试(KMP DP 矩阵快速幂)

    题目链接 设f[i][j]为当前是第i位考号.现在匹配到第j位(已有j-1位和A[]匹配)的方案数 因为假如当前匹配j位,如果选择的下一位与A[j+1]不同,那么新的匹配位数是fail[j]而不是0, ...

  3. bzoj1009: [HNOI2008]GT考试 ac自动机+矩阵快速幂

    https://www.lydsy.com/JudgeOnline/problem.php?id=1009 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9 ...

  4. $bzoj1009-HNOI2008$ $GT$考试 字符串$dp$ 矩阵快速幂

    题面描述 阿申准备报名参加\(GT\)考试,准考证号为\(N\)位数\(x_1,x_2,...,x_n\ (0\leq x_i\leq 9)\),他不希望准考证号上出现不吉利的数字. 他的不吉利数字\ ...

  5. BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法

    标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...

  6. bzoj 1009: [HNOI2008]GT考试【kmp+dp+矩阵快速幂】

    看n和k的范围长得就很像矩阵乘法了 设f[i][j]表示到第i个位置的后缀最长匹配目标串的j位.转移的话显然是枚举0~9,然后选择f[i+1]中能被他转移的加起来,需要用到next数组.然后构造矩阵的 ...

  7. 2019.2.25考试T1, 矩阵快速幂加速递推+单位根反演(容斥)

    \(\color{#0066ff}{题解}\) 然后a,b,c通过矩阵加速即可 为什么1出现偶数次3没出现的贡献是上面画绿线的部分呢? 考虑暴力统计这部分贡献,答案为\(\begin{aligned} ...

  8. [bzoj1009](HNOI2008)GT考试 (kmp+矩阵快速幂加速递推)

    Description 阿 申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学 A1A2...Am(0&l ...

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

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

随机推荐

  1. 极大似然估计(MLE)

    基本思想 模型已定,参数未知 根据已存在的样本,挑选(求出)能让样本以最大概率发生的参数 极大似然估计和最小二乘法最大区别之一 极大似然需要知道概率密度函数(离散型叫分布律) 若总体X属离散型,其分布 ...

  2. 织梦搜索页使用arclist标签

    织梦默认不能在搜索页使用arclist标签,我们对代码做一些小改动即可 打开include/arc.searchview.class.php 一.查找代码: require_once(DEDEINC. ...

  3. ajaxfileupload批量上传文件+图片尺寸限制

    1.首先展示ajaxfileupload代码,在这里修改为批量上传 //ajaxfileupload不展示全部代码,这是修改前与修改后代码对比,目的是上传多个文件 createUploadForm: ...

  4. Java经典编程题50道之二十八

    对10个数进行排序. public class Example28 {    public static void main(String[] args) {        int[] s = { 5 ...

  5. Spring Data与elasticsearch版本对应关系

  6. hbase优化之region合并和压缩

    HBASE操作:(一般先合并region然后再压缩) 一 .Region合并: merge_region   'regionname1','regionname2' ,'true'  --true代表 ...

  7. markdown学习经验

    文章首发于我的github博客 前言 markdown是一种简洁有力的文本编辑语言.由于它十分好用,我将所有的博客都换成了markdown编辑器. 学习方法 工具为先,从工具中学习,熟能生巧. 工具选 ...

  8. 长整形的使用及cin加速

    _int64 和 long long 那么对ACMer来说,最为关心的就是在各个OJ上交题应分别使用哪种方式了.其实方式只有有限的几种: 如果服务器是linux系统,那么定义用long long,IO ...

  9. HDU - 1907 John 反Nimm博弈

    思路: 注意与Nimm博弈的区别,谁拿完谁输! 先手必胜的条件: 1.  每一个小游戏都只剩一个石子了,且SG = 0. 2. 至少有一堆石子数大于1,且SG不等于0 证明:1. 你和对手都只有一种选 ...

  10. 我博客上的围棋js程序

    作为一个围棋爱好者,就决定在博客里加个围棋js程序.于是,申请了博客的js权限,美化美化我的博客. 好在js的语法像C系的,看了看,写个程序应该还是可以的. 围棋里,设计好基本的数据结构: //a是1 ...