Description

阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。

他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0

Input

第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000

Output

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

Sample Input

4 3 100

111

Sample Output

81

Solution

这题还是很无奈的

按照数位dp的思想依次考虑每一位上的数字,考虑设计dp,\(f[i][j]\) 代表考虑完第 \(i\) 位之后,后 \(j\) 位与不吉利数字的前 \(j\) 位相同的方案数

那么最后答案为 \(ans=\sum_{i=0}^{m-1}f[n][i]\)

现在新加进来一个数,对之前的相同的 \(j\) 位造成的影响会有三种情况:

  1. 延长原有的 \(j\) 位,变成 \(j+1\) 位

  2. 直接把原有的 \(j\) 位打回0位

  3. 把原来的 \(j\) 位变短到一个位置,而这个位置,你会发现正好是KMP中求的fail/next数组

那么,\(f[i][j]=f[i-1][j-1]+\sum_{k=1}^mf[i-1][k]*[next[k]=j-1]\)

再进一步,\(f[i][j]=\sum_{k=0}^{m-1}f[i-1][k]*a[k][j]\),其中 \(a[k][j]\) 代表从匹配好 \(k\) 位变成匹配 \(j\) 位的方案数

对于 \(a\) 数组,先KMP求出fail/next数组,然后直接枚举每个位置上的每个数,相当于暴力求得

对于 \(f\) 数组,看上面的式子难道不眼熟吗,这东西显然可以矩阵快速幂优化

然后答案就出来了

注意一下每个人的KMP写法都不一样,求的fail/next数组也会有所不同,但只要能达到效果就可以了,不同的写法最后算 \(a\) 的时候,细节略有不同

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
const int MAXM=400+5;
int n,m,Mod,ans,nexts[MAXM];
char s[MAXM];
struct Matrix{
int a[MAXM][MAXM];
inline void init()
{
memset(a,0,sizeof(a));
}
inline Matrix operator * (const Matrix &A) const {
Matrix B;
for(register int i=0;i<m;++i)
for(register int j=0;j<m;++j)
{
B.a[i][j]=0;
for(register int k=0;k<m;++k)(B.a[i][j]+=(a[i][k]*A.a[k][j]))%=Mod;
}
return B;
};
};
Matrix A,B;
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void KMP()
{
nexts[0]=-1;
for(register int i=1;i<m;++i)
{
int j=nexts[i-1];
while(s[i]!=s[j+1]&&j>=0)j=nexts[j];
if(s[i]==s[j+1])nexts[i]=j+1;
else nexts[i]=-1;
}
}
inline void init()
{
KMP();
for(register int i=0;i<m;++i)
for(register int j='0';j<='9';++j)
{
int k=i;
while(k&&s[k]!=j)k=nexts[k-1]+1;
if(s[k]==j)k++;
if(k!=m)B.a[i][k]++;
}
}
inline Matrix Fast_Matrix(int k)
{
Matrix res;
res.init();
res=B;
--k;
while(k)
{
if(k&1)res=res*B;
B=B*B;
k>>=1;
}
return res;
}
int main()
{
read(n);read(m);read(Mod);
A.init();B.init();
scanf("%s",s);
init();
A.a[0][0]=1;
B=Fast_Matrix(n);
A=A*B;
for(register int i=0;i<m;++i)(ans+=A.a[0][i])%=Mod;
write(ans,'\n');
return 0;
}

【刷题】BZOJ 3262 [HNOI2008]GT考试的更多相关文章

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

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

  2. BZOJ 1009 [HNOI2008]GT考试 (KMP + 矩阵快速幂)

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4266  Solved: 2616[Submit][Statu ...

  3. bzoj 1009: [HNOI2008]GT考试 -- KMP+矩阵

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MB Description 阿申准备报名参加GT考试,准考证号为N位数X1X2.. ...

  4. 题解:BZOJ 1009 HNOI2008 GT考试 KMP + 矩阵

    原题描述: 阿申准备报名参加GT考试,准考证号为N位数 X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学A1A2...Am(0<=Ai&a ...

  5. [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

    题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j ...

  6. BZOJ 1009: [HNOI2008]GT考试(kmp+dp+矩阵优化)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 思路:真的是好题啊! 对于这种题目,很有可能就是dp,$f[i][j]$表示分析到第 ...

  7. bzoj 1009:[HNOI2008]GT考试

    这道题机房n多人好久之前就A了…… 我到现在才做出来…… 一看就是DP+矩阵乘法,但是一开始递推式推错了…… 正确的递推式应该是二维的…… f[i][j] 表示第准考证到第 i 位匹配了 j 位的方案 ...

  8. bzoj 1009 [HNOI2008]GT考试(DP+KMP+矩阵乘法)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1009 [题意] 给定一个字符串T,问长度为n且不包含串T的字符串有多少种. [思路] ...

  9. BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法

    标题效果:给定的长度m数字字符串s.求不包括子s长度n数字串的数目 n<=10^9 看这个O(n)它与 我们不认为这 令f[i][j]长度i号码的最后的字符串j位和s前者j数字匹配方案 例如,当 ...

随机推荐

  1. pandas安装以及出现的问题

    pandas安装以及出现的问题 1.pandas 安装 pandas是Python的第三方库,所以使用前需要安装一下,直接使用pip install pandas就会自动安装,安装成功后显示的以下的信 ...

  2. 廖雪峰git教程学习笔记

    对git来说,没有消息就是最好的消息 使用 git init 把当前目录变为git仓库 要在仓库里加入文件,先在仓库目录新建这个文件后,比如新建一个文件xiaobai.txt,内容为: 在命令行里输入 ...

  3. move.js运动插件

    move.js 运动插件是一款针对元素动画效果的插件.可以运用此插件制作出各类元素效果. 插件GitHub地址:https://github.com/visionmedia/move.js 下面整理学 ...

  4. 控制台报错: SCRIPT1006: Expected ')'

    今天做网站的时候,jsp页面取一个值死活取不出来. <script> if(${not empty requestScope.article.articleId}){ alert(${re ...

  5. RAID系列技术详解

    1.RAID 0 RAID 0是把n个物理磁盘虚拟成一个逻辑磁盘,即形成RAID 0的各个物理磁盘会组成一个逻辑上连续,物理上也连续的虚拟磁盘.一级磁盘控制器(指使用这个虚拟磁盘的控制器,如果某台主机 ...

  6. VMware两台虚拟机之间文件共享

    虚拟机A的文件拷贝到虚拟机B scp[参数][原路径][目标路径] eg: scp -r root@192.168.0.172:/home/rookie/下载/ /home/rooookie/下载/ ...

  7. MySQL基础(一)

    首先需要安装MySOL,这里我是在windows环境下安装的,具体教程可以参考https://www.cnblogs.com/xsmile/p/7753984.html,不过要注意安装过程可能会不太顺 ...

  8. ES6----Proxy(一)

    Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程. 听起来好像很绕,可以简单这样理解,Proxy相当于 ...

  9. Linux下lshw,lsscsi,lscpu,lsusb,lsblk硬件查看命令

    Linux下lshw,lsscsi,lscpu,lsusb,lsblk硬件查看命令 2016-12-14 何敏杰 1条评论 544次浏览   注意:如有提示命令找不到command not found ...

  10. C++ 类 析构函数

    一.析构函数的定义 析构函数为成员函数的一种,名字与类名相同,在前面加‘~’没有参数和返回值在C++中“~”是位取反运算符.一个类最多只能有一个析构函数.析构函数不返回任何值,没有函数类型,也没有函数 ...