【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. typedef void(*Fun)(void);

    typedef void(*Fun)(void); 函数类似于数组,函数名就是它的首地址: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ...

  2. 如何在关闭ssh连接的情况下,让程序继续运行?

    [http://blog.csdn.net/smstong/article/details/5872309] 对Unix,Linux类服务器维护经常是通过ssh完成的,而有些操作比较费时,如更新程序等 ...

  3. 使用Nginx实现灰度发布

    灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式.AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B ...

  4. win7本地连接消失

    可能原因一 驱动程序错误: 右键"计算机"图标 - "属性" - 设备管理器现在在设备管理器下面找到"网络适配器",在下面的网卡驱动中发现有 ...

  5. dedecms织梦判断当前页面是首页、栏目页还是文章页

    根据全局变量$GLOBALS['_sys_globals']['curfile']的值来判断. 首页parview:列表页listview:文章页archives 应用示例: {dede:php}if ...

  6. SQL SERVER FOR LINUX初体验

    今天得空,就在Ubuntu17.04上安装了SQL SERVER 2017体验下,总体来说还是不错的. 在Ubuntu上安装SQL SERVER 2017还是比较方便的,只需几条命令即可: curl ...

  7. ci框架基础知识点

    一.路由 1.index.php/test/hello->控制器test的hello方法 2. 也可以手动配置路由   app/config/routes.php中     I:$route[' ...

  8. hql语句中的select字句和from 字句

    package com.imooc.model; import java.util.List; import java.util.Map; import org.hibernate.Query; im ...

  9. C语言_初步了解一下指针

    指针的基本概念 在计算机中,所有的数据都是存放在存储器中的. 一般把存储器中的一个字节称为一个内存单元, 不同的数据类型所占用的内存单元数不等,如整型量占2个单元,字符量占1个单元等.为了正确地访问这 ...

  10. 地牢逃脱 (BFS)

    题意:给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指 ...