【BZOJ1009】GT考试(KMP算法,矩阵快速幂,动态规划)
【BZOJ1009】GT考试(KMP算法,矩阵快速幂,动态规划)
题面
题解
看到这个题目
化简一下题意
长度为\(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算法,矩阵快速幂,动态规划)的更多相关文章
- [BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂)
[BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂) 题面 阿申准备报名参加GT考试,准考证号为N位数X1X2-.Xn,他不希望准考证号上出现不吉利的数字.他的不吉利数学A ...
- BZOJ.1009.[HNOI2008]GT考试(KMP DP 矩阵快速幂)
题目链接 设f[i][j]为当前是第i位考号.现在匹配到第j位(已有j-1位和A[]匹配)的方案数 因为假如当前匹配j位,如果选择的下一位与A[j+1]不同,那么新的匹配位数是fail[j]而不是0, ...
- bzoj1009: [HNOI2008]GT考试 ac自动机+矩阵快速幂
https://www.lydsy.com/JudgeOnline/problem.php?id=1009 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9 ...
- $bzoj1009-HNOI2008$ $GT$考试 字符串$dp$ 矩阵快速幂
题面描述 阿申准备报名参加\(GT\)考试,准考证号为\(N\)位数\(x_1,x_2,...,x_n\ (0\leq x_i\leq 9)\),他不希望准考证号上出现不吉利的数字. 他的不吉利数字\ ...
- BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法
标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...
- bzoj 1009: [HNOI2008]GT考试【kmp+dp+矩阵快速幂】
看n和k的范围长得就很像矩阵乘法了 设f[i][j]表示到第i个位置的后缀最长匹配目标串的j位.转移的话显然是枚举0~9,然后选择f[i+1]中能被他转移的加起来,需要用到next数组.然后构造矩阵的 ...
- 2019.2.25考试T1, 矩阵快速幂加速递推+单位根反演(容斥)
\(\color{#0066ff}{题解}\) 然后a,b,c通过矩阵加速即可 为什么1出现偶数次3没出现的贡献是上面画绿线的部分呢? 考虑暴力统计这部分贡献,答案为\(\begin{aligned} ...
- [bzoj1009](HNOI2008)GT考试 (kmp+矩阵快速幂加速递推)
Description 阿 申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学 A1A2...Am(0&l ...
- bzoj1009 [HNOI2008]GT考试——KMP+矩阵快速幂优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 字符串计数DP问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我... 首 ...
随机推荐
- MySQL数据库基础
MySQL数据库基础 本文的所有操作是基于CMD环境,MySQL通过在命令行中输入SQL语句对数据库进行操作.配置问题可参考<打通MySQL的操作权限>中的内容,该文算是针对前期的环境配置 ...
- Go语言获取命令行参数
package main import ( "os" "fmt" ) func main() { args := os.Args //获取用户输入的所有参数 { ...
- Lua内存分析工具
最近给公司写了一个lua内存分析工具,可以非常方便的分析出Lua内存泄露问题,有图形化界面操作,方便手机端上传快照等功能 内存分析我是在c语言端写的,也有人写过lua端的分析工具,也蛮好用的,不过lu ...
- FFT模板(多项式乘法)
FFT模板(多项式乘法) 标签: FFT 扯淡 一晚上都用来捣鼓这个东西了...... 这里贴一位神犇的博客,我认为讲的比较清楚了.(刚好适合我这种复数都没学的) http://blog.csdn.n ...
- [APIO2015]雅加达的摩天楼
Description 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 " ...
- ajaxfileupload批量上传文件+图片尺寸限制
1.首先展示ajaxfileupload代码,在这里修改为批量上传 //ajaxfileupload不展示全部代码,这是修改前与修改后代码对比,目的是上传多个文件 createUploadForm: ...
- eslint规则
碰到eslint报错, 把错误的提示拷贝在这里Ctrl + F找到复制到eslint.js里面就行了. "off"或者0,不启用这个规则 "warn"或者1,出 ...
- CSS布局(一) 盒子模型
一.盒子模型 标准盒子模型 从下图可以看到标准 w3c 盒子模型的范围包括 content.padding.border.margin,并且 content 部分不包含其他部分. 怪异盒子模型 从下图 ...
- 【mysql】 操作 收集持续更新
一个字段可能对应多条数据,用mysql实现将多行数据合并成一行数据 GROUP_CONCAT(Name SEPARATOR ',') 需注意: 1.GROUP_CONCAT()中的值为你要合并的数据的 ...
- w !sudo tee %
w !sudo tee % 该命令可用于保存有权限的写文件