【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问题啊...连题解都看了好多好久才明白,别提自己想出来的蒟蒻我... 首 ...
随机推荐
- 极大似然估计(MLE)
基本思想 模型已定,参数未知 根据已存在的样本,挑选(求出)能让样本以最大概率发生的参数 极大似然估计和最小二乘法最大区别之一 极大似然需要知道概率密度函数(离散型叫分布律) 若总体X属离散型,其分布 ...
- 织梦搜索页使用arclist标签
织梦默认不能在搜索页使用arclist标签,我们对代码做一些小改动即可 打开include/arc.searchview.class.php 一.查找代码: require_once(DEDEINC. ...
- ajaxfileupload批量上传文件+图片尺寸限制
1.首先展示ajaxfileupload代码,在这里修改为批量上传 //ajaxfileupload不展示全部代码,这是修改前与修改后代码对比,目的是上传多个文件 createUploadForm: ...
- Java经典编程题50道之二十八
对10个数进行排序. public class Example28 { public static void main(String[] args) { int[] s = { 5 ...
- Spring Data与elasticsearch版本对应关系
- hbase优化之region合并和压缩
HBASE操作:(一般先合并region然后再压缩) 一 .Region合并: merge_region 'regionname1','regionname2' ,'true' --true代表 ...
- markdown学习经验
文章首发于我的github博客 前言 markdown是一种简洁有力的文本编辑语言.由于它十分好用,我将所有的博客都换成了markdown编辑器. 学习方法 工具为先,从工具中学习,熟能生巧. 工具选 ...
- 长整形的使用及cin加速
_int64 和 long long 那么对ACMer来说,最为关心的就是在各个OJ上交题应分别使用哪种方式了.其实方式只有有限的几种: 如果服务器是linux系统,那么定义用long long,IO ...
- HDU - 1907 John 反Nimm博弈
思路: 注意与Nimm博弈的区别,谁拿完谁输! 先手必胜的条件: 1. 每一个小游戏都只剩一个石子了,且SG = 0. 2. 至少有一堆石子数大于1,且SG不等于0 证明:1. 你和对手都只有一种选 ...
- 我博客上的围棋js程序
作为一个围棋爱好者,就决定在博客里加个围棋js程序.于是,申请了博客的js权限,美化美化我的博客. 好在js的语法像C系的,看了看,写个程序应该还是可以的. 围棋里,设计好基本的数据结构: //a是1 ...