之前学矩阵乘的时候做的题,当时因为不会\(kmp\)搜索一稀里糊涂过去了,现在填个坑。

头图

是\(Logos\)!


P3193 [HNOI2008] GT考试

题链:洛谷 题库

题目大意:

求有多少个长度为\(n\)的数字串的子串中不包含给出的长度为\(m\)位的串,范围 \(n <= 1e9\),$ m <= 20$。

思路:

首先考虑DP,令\(zl[i][j]\)为原串匹配到第\(i\)位,短串最多可以匹配到第\(j\)位的方案数。

那么显然答案为:

\[\sum_{i=0}^{m-1}zl[n][i]
\]

状态转移方程为:

\[zl[i][j]=\sum_{k=0}^{9}zl[i-1][p]
\]

其中的\(p\)不一定是\(0\)或者\(j-1\),因为加入字符\(k\)后,会有三种情况产生:

  1. 与原串中的下一个字符匹配;
  2. 失配,无法与任何字符相匹配;
  3. 重新与原串的另一个前缀匹配。

那么上面的式子就无法支持我们完成之后的操作了,所以我们换一种写法。

令\(dh[k][j]\)为一个匹配了长度为\(k\)的串,有多少种增加数字的方法,使得与原串匹配的长度变成\(j\)。

状态转移方程为:

\[zl[i][j]=\sum_{k=0}^{m-1}zl[i][k] \times dh[k][j]
\]

由于我们知道原串,所以整个\(dh\)数组是固定的,我们可以预处理出这个数组。方法是用\(kmp\)求出\(next\)数组后,枚举匹配长度\(k\)和字符\(ch\),暴力计算出能匹配到前缀的长度。

那么,由于这道题是矩阵乘法专题里的\(dh\)数组恒不变,显然能想到用矩阵乘法的相关知识来解决。

因为我们最后只需要第\(n\)行矩阵,所以我们把每一行\(zl[i][j]\)抽象成一行,\(m-1\)列的矩阵\(hdl[i]\),可推导出\(hdl[i]=hdl[i-1]*yns\),那么,\(hdl[n]=hdl[0]*yns^n\)。

矩阵快速幂求出\(yns^n\),再用矩阵乘法使其与\(hdl\)相乘,即可得出最终矩阵,再把答案一加一模就ok啦。

code:

#include<bits/stdc++.h>
#define fo(x,y,z) for(int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(int (x)=(y);(x)>=(z);(x)--)
typedef long long ll;
namespace Aventurine
{
inline int qr()
{
char ch=getchar();int x=0,f=1;
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
return x*f;
}
inline void qw(int x)
{
if(!x)
return;
qw(x/10);
putchar(x%10+'0');
}
inline void qkg(int x)
{
if(x==0)
putchar('0');
else
qw(x);
putchar(' ');
}
inline void qhh(int x)
{
if(x==0)
putchar('0');
else
qw(x);
putchar('\n');
}
}
#define qr qr()
using namespace std;
using namespace Aventurine;
const int Ratio=0;
const int N=55;
const int maxi=INT_MAX;
int n,len,mod,ans;
int kmp[N];
char s[N];
struct rmm
{
int a[N][N];
rmm()
{//一定要初始化!一定要初始化!一定要初始化!
memset(a,0,sizeof a);
}//在结构体中定义的数组需要初始化!
}yns,hdl;
rmm operator*(rmm a,rmm b)//矩阵乘
{
rmm c;
fo(i,0,len-1)
fo(j,0,len-1)
fo(k,0,len-1)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]%mod+mod)%mod;
return c;
}
rmm operator^(rmm a,int t)//矩阵快速幂
{
rmm b;
fo(i,0,len-1)
b.a[i][i]=1;
while(t)
{
if(t&1)
b=b*a;
a=a*a;
t>>=1;
}
return b;
}
namespace Wisadel
{
void Wprekmp()//kmp初始化
{
int j=0;
fo(i,2,len)
{
while(j&&s[j+1]!=s[i])
j=kmp[j];
if(s[j+1]==s[i])
j++;
kmp[i]=j;
}
}
void Wwork()
{
fo(i,0,len-1)
for(char ch='0';ch<='9';ch++)
{//枚举添加的字符
int j=i;
while(j&&s[j+1]!=ch)
j=kmp[j];
if(s[j+1]==ch)
j++;
yns.a[i][j]=(yns.a[i][j]+1)%mod;
}
hdl.a[0][0]=1;//即为hdl[0]
yns=yns^n;
hdl=hdl*yns;
fo(i,0,len-1)
ans=(ans+hdl.a[0][i])%mod;
}
short main()
{
n=qr,len=qr,mod=qr;
scanf("%s",s+1);
Wprekmp();
Wwork();
printf("%d\n",ans);
return Ratio;
}
}
int main(){return Wisadel::main();}

完结撒花
我放两张

“维什戴尔”,就把名字签这里,对吧?殿下告诉我,这个名字的意思是“许愿一个家”,但我从不许愿。啊?字太丑?还轮不到你来指指点点。



谁有W的好图啊aa球球了QwQ

P3193 [HNOI2008] GT考试 题解的更多相关文章

  1. 【KMP】【矩阵加速】【递推】洛谷 P3193 [HNOI2008]GT考试 题解

        看出来矩阵加速也没看出来KMP…… 题目描述 阿申准备报名参加 GT 考试,准考证号为\(N\)位数\(X_1,X_2…X_n(0\le X_i\le9)\),他不希望准考证号上出现不吉利的数 ...

  2. bzoj1009 / P3193 [HNOI2008]GT考试

    P3193 [HNOI2008]GT考试 设$f[i][j]$表示主串匹配到第$i$个位置,不吉利数字匹配到第$j$个位置 $g[i][j]$表示加上某数字使子串原来最多能匹配到第$i$个数字,现在只 ...

  3. P3193 [HNOI2008]GT考试(KMP+矩阵乘法加速dp)

    P3193 [HNOI2008]GT考试 思路: 设\(dp(i,j)\)为\(N\)位数从高到低第\(i\)位时,不吉利数字在第\(j\)位时的情况总数,那么转移方程就为: \[dp(i,j)=dp ...

  4. BZOJ1009:[HNOI2008]GT考试——题解

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

  5. 洛谷P3193 [HNOI2008]GT考试(dp 矩阵乘法)

    题意 题目链接 Sol 设\(f[i][j]\)表示枚举到位置串的第i位,当前与未知串的第j位匹配,那么我们只要保证在转移的时候永远不会匹配即可 预处理出已知串的每个位置加上某个字符后能转移到的位置, ...

  6. luogu P3193 [HNOI2008]GT考试

    传送门 单串匹配显然用\(kmp\) 一个暴力的dp是设\(f_{i,j}\),表示前\(i\)位,正在匹配给定串第\(j\)位的方案,转移就枚举下一位放什么,然后使用\(kmp\)看会匹配到给定串的 ...

  7. 洛谷P3193 [HNOI2008]GT考试 kmp+dp

    正解:kmp+dp+矩阵优化 解题报告: 传送门! 啊刚说想做矩阵优化dp的字符串题就找到辣QwQ虽然不是AC自动机的但都差不多嘛QwQ 首先显然可以想到一个dp式?就f[i][j]:凑出i位了,在s ...

  8. P3193 [HNOI2008]GT考试

    传送门 容易看出是道DP 考虑一位一位填数字 设 f [ i ] [ j ] 表示填到第 i 位,在不吉利串上匹配到第 j 位时不出现不吉利数字的方案数 设 g [ i ] [ j ] 表示不吉利串匹 ...

  9. 洛谷P3193 [HNOI2008]GT考试(KMP,矩阵)

    传送门 大佬讲的真吼->这里 首先考虑dp,设$f[i][j]$表示长串匹配到第$i$位,短串最多匹配到$j$位时的方案数 那么答案就是$\sum_{i=0}^{m-1}f[n][i]$ 然后考 ...

  10. [HNOI2008]GT考试 题解

    这题比较难搞.考虑设计状态:\(f_{i,j}\) 表示当前考虑到 \(X_i\) 位,且 \(X\) 的后 \(j\) 位刚好与 \(A\) 列匹配时的方案数.最终答案为 \(\sum_{i=0}^ ...

随机推荐

  1. #LCA,二分,树上差分#洛谷 2680 运输计划

    题目 一棵树,每条边上都有边权,现在选择一条边将边权变为0,使\(m\)条路径边权和其中一条的最大值最小,问这个值 分析 由于大于最终结果的一定可行,小于最终结果的一定不可行,所以二分答案,首先答案以 ...

  2. 陈海波:OpenHarmony技术领先,产学研深度协同,生态蓬勃发展

      11月4日,以"技术筑生态,智联赢未来"为主题的第二届OpenHarmony技术大会在北京隆重举办.本次大会由OpenAtom OpenHarmony(简称"Open ...

  3. Seaborn分布数据可视化---散点分布图

    散点分布图 综合表示散点图和直方分布图. Jointplot() 绘制二变量或单变量的图形,底层是JointGrid(). sns.jointplot( x, y, data=None, kind=' ...

  4. 初学STM32 SDIO (二)

    ​ SD命令由主机发出,以广播命令和寻址命令为例,广播命令是针对与SD主机总线连接的所有从设备发送的,寻址命令是指定某个地址设备进行命令传输. 1.SD命令格式 SD命令格式固定为48bit,都是通过 ...

  5. .NET Aspire预览5版本 发布

    2024年4月11日发布了.NET Aspire预览5版本,这个版本引入了对AWS的支持,并对Azure功能进行了改进.重点内容包括拆分Aspire.Hosting和Aspire.Hosting.Az ...

  6. 新一期HarmonyOS认证正式发布,速来围观!

    原文:https://mp.weixin.qq.com/s/mvXLnJM9VKTyq8mi9BfY1w,点击链接查看更多技术内容.   华为认证HarmonyOS应用开发高级工程师HCIP-Harm ...

  7. CentOS编译安装Nginx1.5.2+PHP5.5.1+ MySQL 5.6.10

    CentOS编译安装Nginx1.5.2+PHP5.5.1+ MySQL 5.6.10 时间:2013-11-15 23:39 来源:blog.s135.com  作者:张宴的博客  举报  点击:1 ...

  8. 局部区块多个报表 TAB 页切换及局部区块的参数查询

    在企业的业务系统中,如何从纷繁复杂的数据中抽丝剥茧看到关键数据信息呢?一个重要的途径就是将企业和各部门运营中关键的 KPI 集中在一起显示,同时尽量省去在企业的各个业务系统中分别查找数据. 下面是我近 ...

  9. python 代码编写环境及编辑器配置

    前言 关于python 环境编辑器的配置. 正文 第一步:python解释器,到网上下载安装下就行. 网址:https://www.python.org/downloads/windows/ 值得注意 ...

  10. Scratch3自定义积木块之新增积木块

    在Scratch3.0的二次开发中,新功能的研发和扩展离不开积木块的添加,这篇主要讲解Scratch3.0中新增积木块部分 Scratch3.0中对于新增积木块有两种方式: 1. 初始化积木块方式   ...