题目链接:https://www.luogu.org/problemnew/show/P3193#sub

题目描述

阿申准备报名参加 GT 考试,准考证号为 N 位数 X1,X2…Xn(0 <= Xi <= 9) ,他不希望准考证号上出现不吉利的数字。 他的不吉利数学 A1​,A2​…Am​(0≤Ai​≤9) 有 M 位,不出现是指 X1​,X2​…Xn​ 中没有恰好一段等于 A1​,A2​…Am​ ,A1​

输入输出格式

输入格式:

第一行输入N,M,K.接下来一行输入M位的数。

输出格式:

阿申想知道不出现不吉利数字的号码有多少种,输出模 K 取余的结果。

输入输出样例

输入样例#1:

4 3 100
111
输出样例#1:

81

说明

N≤109,M≤20,K≤1000

题目大意,给定长为m的子串,统计长度为n的不包含该子串的串的方案数

考虑DP解决,f[i][j]表示长串匹配到第 i 位,短串最多可以匹配到第 j 位的方案数(即表示长度为i的长串,最后j个可以匹配短串前j位的方案数)

状态转移方程如下:

f[i+1][j]=f[i][k]*g[j][k](0<=k<m)

最终答案就是∑f[n][i](0<=i<m)(这显然正确,仔细想想就发现这些i代表的状态互相独立,且并集包含了所有的状态)

g[i][j]表示对于短串,原本匹配了i位,匹配下一位时匹配到第j位的这个下一位的方案数

图一,短串匹配了j位,长串匹配到了i位

图2,长串继续向下匹配,短串失配

图3,短串转移到下一个可以匹配的地方

注意由于new是我们任意填的,因此我们只需考虑短串的下一个匹配的位置,即KMP算法中的next数组

上面三幅图实际上就是匹配的过程,是为了让读者更好的理解g数组的含义

下面我们考虑怎么求g数组。回顾g数组的含义,我们发现实际上只和短串有关(上面说了,new是任意填的)。KMP预处理出g数组,若我原来匹配了i位,枚举下一个数字,不断转移next数组直到匹配成功,最终得到一个可以匹配的位置k,然后我们让f[i][k]++统计方案数

发现n的取值过大且上述状态转移方程可用矩阵快速幂优化。注意每次乘上转移矩阵得到的矩阵存储的实际上是状态,因此其实矩阵的宽都是1来着。

考虑到每次我们转移的矩阵g是不变的,于是我们可以很快结束这个问题

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; const int N=;
int n,m,mod;
int next[N],a[N];
char s[N];
struct matrix
{
int r,c,num[N][N];//矩阵的长宽
matrix(){memset(num,,sizeof(num));}
void init()
{
for (int i=;i<N;i++)
num[i][i]=;
}
}g,A;
matrix mul(matrix a,matrix b)
{
matrix ans;
ans.r=a.r;ans.c=b.c;
for (int i=;i<=a.r;i++)
for (int j=;j<=b.c;j++)
{
ans.num[i][j]=;
for (int k=;k<=ans.c;k++)
ans.num[i][j]=(ans.num[i][j]+a.num[i][k]*b.num[k][j])%mod;
}
return ans;
}
matrix qpow(matrix a,int x)
{
matrix ans;
ans.init();
for (;x;x>>=,a=mul(a,a)) if (x&) ans=mul(ans,a);
return ans;
}
int main()
{
scanf("%d%d%d",&n,&m,&mod);
scanf("%s",s);
for (int i=;i<m;i++) a[i]=s[i]-'';a[m]=0x3f3f3f3f;
for (int i=,j=;i<m;i++)//计算出next数组
{
while (j&&(a[i]!=a[j])) j=next[j];
j+=(a[i]==a[j]);
next[i+]=j;
}
for (int i=;i<m;i++)
for (int j=;j<;j++)//预处理出g数组
{
int k=i;
while (k&&a[k]!=j) k=next[k];
k+=(a[k]==j);
if (k<m) g.num[i][k]++;//i位可以转移到k位
}
A.num[][]=;A.r=;g.c=g.r=A.c=m-;//初始化
A=mul(A,qpow(g,n));
int ans=;
for (int i=;i<m;i++) {ans+=A.num[][i];ans%=mod;}//统计每个状态的答案
printf("%d",ans);
return ;
}

[HNOI2008] GT考试(DP+矩阵快速幂+KMP)的更多相关文章

  1. BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )

    写了一个早上...就因为把长度为m的也算进去了... dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j) ...

  2. [BZOJ1009][HNOI2008]GT考试 DP+矩阵快速幂+KMP

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1009 我们令$dp(i,j)$表示已经填了$i$位,而且后缀与不幸运数字匹配了$j$位,那 ...

  3. 【bzoj1009】[HNOI2008]GT考试(矩阵快速幂优化dp+kmp)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1009 这道题一看数据范围:$ n<=10^9 $,显然不是数学题就是矩乘快速幂优 ...

  4. [BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂)

    [BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂) 题面 阿申准备报名参加GT考试,准考证号为N位数X1X2-.Xn,他不希望准考证号上出现不吉利的数字.他的不吉利数学A ...

  5. bnuoj 34985 Elegant String DP+矩阵快速幂

    题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 We define a kind of strings as elegant s ...

  6. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  7. 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂

    [题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...

  8. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  9. BZOJ5298 CQOI2018 交错序列 【DP+矩阵快速幂优化】*

    BZOJ5298 CQOI2018 交错序列 [DP+矩阵快速幂优化] Description 我们称一个仅由0.1构成的序列为"交错序列",当且仅当序列中没有相邻的1(可以有相邻 ...

随机推荐

  1. 将maven中央仓库不存在的jar包添加到本地仓库

    这里有2个案例,需要手动发出Maven命令包括一个 jar 到 Maven 的本地资源库. 要使用的 jar 不存在于 Maven 的中心储存库中. 您创建了一个自定义的 jar ,而另一个 Mave ...

  2. [ReactVR] Add Shapes Using 3D Primitives in React VR

    React VR ships with a handful of 3D primitives. We'll importprimitives like <Sphere/>, <Box ...

  3. 判断QString是否为纯数字,查找自身最长重复子字符串

    1.判断QString是否为纯数字 bool IsDigitString(QString strSource) { bool bDigit = false; if (strSource.isEmpty ...

  4. Linux下DNS服务器搭建详解

    Linux下DNS服务器搭建详解 DNS  即Domain Name System(域名系统)的缩写,它是一种将ip地址转换成对应的主机名或将主机名转换成与之相对应ip地址的一种机制.其中通过域名解析 ...

  5. oracle 11g RAC 的一些基本概念

    一.脑裂以及对策 脑裂(split-brain)是集群中的一个糟糕的情况:集群中的所有集群正在工作的时候,内部通讯被断开.这种情况下,集群被分成了几个部分,每个部分的集群软件都会尝试去接管其他节点的资 ...

  6. php正则检测字符串由单一字符组成

    $str = 'aaa' $firstChar = substr($str , 0, 1); $pattern = "/^[$firstChar]+$/"; $ret = preg ...

  7. MSSQL读取xml字符串到临时表

    DECLARE @hdoc int DECLARE @doc xml SET @doc ='<CityValueSet> <CityItem> <CityId>20 ...

  8. HDU 1506 Largest Rectangle in a Histogram【DP】

    题意:坐标轴上有连续的n个底均为1,高为h[i]的矩形,求能够构成的最大矩形的面积. 学习的别人的代码 @_@ 看底的坐标怎么找的看了好一会儿--- 记l[i]为矩形的底的左边的坐标,就将它一直向左扩 ...

  9. Converting Legacy Chrome IPC To Mojo

    Converting Legacy Chrome IPC To Mojo Looking for Mojo Documentation? Contents Overview Deciding What ...

  10. Debian9.5系统DHCP服务器ISC DHCP软件配置说明

    DHCP 全称Dynamic Host configuration protocol, 动态主机配置协议.是一个局域网的网络协议,使用UDP协议工作,它可以为客户机自动分配IP地址.子网掩码以及缺省网 ...