【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. MySQL数据库基础

    MySQL数据库基础 本文的所有操作是基于CMD环境,MySQL通过在命令行中输入SQL语句对数据库进行操作.配置问题可参考<打通MySQL的操作权限>中的内容,该文算是针对前期的环境配置 ...

  2. Go语言获取命令行参数

    package main import ( "os" "fmt" ) func main() { args := os.Args //获取用户输入的所有参数 { ...

  3. Lua内存分析工具

    最近给公司写了一个lua内存分析工具,可以非常方便的分析出Lua内存泄露问题,有图形化界面操作,方便手机端上传快照等功能 内存分析我是在c语言端写的,也有人写过lua端的分析工具,也蛮好用的,不过lu ...

  4. FFT模板(多项式乘法)

    FFT模板(多项式乘法) 标签: FFT 扯淡 一晚上都用来捣鼓这个东西了...... 这里贴一位神犇的博客,我认为讲的比较清楚了.(刚好适合我这种复数都没学的) http://blog.csdn.n ...

  5. [APIO2015]雅加达的摩天楼

    Description 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 " ...

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

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

  7. eslint规则

    碰到eslint报错, 把错误的提示拷贝在这里Ctrl + F找到复制到eslint.js里面就行了. "off"或者0,不启用这个规则 "warn"或者1,出 ...

  8. CSS布局(一) 盒子模型

    一.盒子模型 标准盒子模型 从下图可以看到标准 w3c 盒子模型的范围包括 content.padding.border.margin,并且 content 部分不包含其他部分. 怪异盒子模型 从下图 ...

  9. 【mysql】 操作 收集持续更新

    一个字段可能对应多条数据,用mysql实现将多行数据合并成一行数据 GROUP_CONCAT(Name SEPARATOR ',') 需注意: 1.GROUP_CONCAT()中的值为你要合并的数据的 ...

  10. w !sudo tee %

    w !sudo tee % 该命令可用于保存有权限的写文件