[BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂)
[BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂)
题面
阿申准备报名参加GT考试,准考证号为N位数X1X2….Xn,他不希望准考证号上出现不吉利的数字。他的不吉利数学A1A2…Am有M位,不出现是指X1X2…Xn中没有恰好一段等于A1A2…Am. A1和X1可以为0
\(0 \leq X_i \leq 9,0\leq Ai\leq 9,m \leq 20,n \leq 10^9\)
分析
先考虑暴力的思路,设\(dp[i][j]\)表示前i位数与不吉利数字匹配了前j位的方案数
那么\(dp[i][f(j,c)]=\sum dp[i-1][j] (c \in[0,9])\)
实际上就是从0~9枚举第i位的数字,然后更新匹配的位数。其中\(f(j,c)\)表示加入数字c后的匹配位数。
但是\(n \leq 10^9\),直接dp显然会超时,发现每层转移都是一样的,所以可以矩阵快速幂优化
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000
#define maxm 20
using namespace std;
typedef long long ll;
char t[maxm+5];
int nex[maxm+5];
void get_nex(char *a){
int len=strlen(a+1);
for(int i=2,j=0;i<=len;i++){
while(j>0&&a[j+1]!=a[i]) j=nex[j];
if(a[j+1]==a[i]) j++;
nex[i]=j;
}
}
int n,m,mod;
int match(int j,char c){
while(j>0&&t[j+1]!=c) j=nex[j];
if(t[j+1]==c) j++;
return j;
}
struct matrix{
ll x[maxn+5][maxn+5];
void set(int p){
if(p==0){
for(int i=0;i<m;i++) for(int j=0;j<m;j++) x[i][j]=0;
}else{
for(int i=0;i<m;i++) for(int j=0;j<m;j++) x[i][j]=0;
for(int i=0;i<m;i++) x[i][i]=1;
}
}
void print(){
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
printf("%lld ",x[i][j]);
}
printf("\n");
}
}
friend matrix operator * (matrix a,matrix b){
matrix ans;
ans.set(0);
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
for(int k=0;k<m;k++){
ans.x[i][j]+=a.x[i][k]*b.x[k][j]%mod;
ans.x[i][j]%=mod;
}
}
}
return ans;
}
};
matrix fast_pow(matrix x,int k){
matrix ans;
ans.set(1);
while(k){
if(k&1) ans=ans*x;
x=x*x;
k>>=1;
}
return ans;
}
int main(){
scanf("%d %d %d",&n,&m,&mod);
scanf("%s",t+1);
get_nex(t);
// dp[0][0]=1;
// for(int i=1;i<=n;i++){
// for(int j=0;j<m;j++){
// for(char ch='0';ch<='9';ch++){
// int k=match(j,ch);
// dp[i][k]+=dp[i-1][j];
// dp[i][k]%=mod;
// }
// }
// }
matrix tp,ans;
tp.set(0);
for(int j=0;j<m;j++){
for(char ch='0';ch<='9';ch++){
int k=match(j,ch);
tp.x[j][k]++;
}
}
// tp.print();
ans=fast_pow(tp,n);
// ans.print();
ll res=0;
for(int j=0;j<m;j++){
res+=ans.x[0][j];
res%=mod;
}
printf("%lld\n",res);
}
[BZOJ1009] [HNOI2008] GT考试(KMP+dp+矩阵快速幂)的更多相关文章
- 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考试 (KMP & dp & 矩阵乘法)
Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字. 他的不吉利数学A1A2...Am(0< ...
- $bzoj1009-HNOI2008$ $GT$考试 字符串$dp$ 矩阵快速幂
题面描述 阿申准备报名参加\(GT\)考试,准考证号为\(N\)位数\(x_1,x_2,...,x_n\ (0\leq x_i\leq 9)\),他不希望准考证号上出现不吉利的数字. 他的不吉利数字\ ...
- 【BZOJ-1009】GT考试 KMP+DP+矩阵乘法+快速幂
1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2745 Solved: 1694[Submit][Statu ...
- bzoj 1009: [HNOI2008]GT考试【kmp+dp+矩阵快速幂】
看n和k的范围长得就很像矩阵乘法了 设f[i][j]表示到第i个位置的后缀最长匹配目标串的j位.转移的话显然是枚举0~9,然后选择f[i+1]中能被他转移的加起来,需要用到next数组.然后构造矩阵的 ...
- [BZOJ1009][HNOI2008]GT考试(KMP+DP)
[不稳定的传送门 Solution dp[i][j]表示前i个字符当前匹配到不吉利串的第j个,即当前方案的后缀等于不吉利串前缀 然而由于n过大,不能直接转移,用矩阵优化 Code #include & ...
- [bzoj1009](HNOI2008)GT考试 (kmp+矩阵快速幂加速递推)
Description 阿 申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学 A1A2...Am(0&l ...
- 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 ...
随机推荐
- jprofiler 监听远程java项目
1.下载.安装windows和linux版的jprofile.注意:若监控的是springboot.springcloud项目,切记本地和服务器上的jprofile要版本保持一致,本人亲自踩过坑. 官 ...
- HDU 3669 [Cross the Wall] DP斜率优化
问题分析 首先,如果一个人的\(w\)和\(h\)均小于另一个人,那么这个人显然可以被省略.如果我们将剩下的人按\(w[i]\)递增排序,那么\(h[i]\)就是递减. 之后我们考虑DP. 我们设\( ...
- MySQ彻底删除与安装配置
彻底删除 1.查看 MySQL 安装了哪些东西 rpm -qa |grep -i mysql 2.卸载 -.el7.x86_64 -.el7.x86_64 .noarch -.el7.x86_64 - ...
- C++入门经典-例4.11-名称空间的定义和使用
1:名称空间,也成为名字空间.命名空间,关键字为namespace.我们经常使用这样一条语句: using namespace std: 我们要使用标准输入输出流,除了包含它们所在的头文件外,还必须使 ...
- mysql5.6 varchar长度不同的情况下group by的效率
varchar长度短的情况下,基于这个字段的group by效率更高.所以开发在设计表的时候要使该字段在满足业务需求的情况下尽可能的小. ps:本想找源码看看代码那是怎么处理的,直接用vim看文件太累 ...
- 4. 获取当前的文件夹的路径,以及当前文件名的路径 os.path.realpath
使用os.path.realpath(__file__) 获得当前的文件夹的路径名, 使用os.path.split 进行路径切割 import os src, _= os.path.split(os ...
- vue问题二:vue打包时产生的问题
vue项目打包问题:vue中默认的config/index.js的配置的详细理解: 参考文档:https://blog.csdn.net/qq_34611721/article/details/809 ...
- CPU处理多任务——中断与轮询方式比较
中断方式与轮询方式比较 中断的基本概念 程序中断通常简称中断,是指CPU在正常运行程序的过程中,由于预选安排或发生了各种随机的内部或外部事件,使CPU中断正在运行的程序,而转到为相应的服务程序去处 ...
- 代码实现:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%; 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提成7.5%; 20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于40万元的部分,可提成3%; 60万到100万之间时,高于60万元的部分,可提成1.5%,高于100万元时,超过100万元
import java.util.Scanner; /* 企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%: 利润高于10万元,低于20万元时,低于10万元的部分按10%提成 ...
- windows 10 右键菜单 使用vscode打开 快捷键
呼出菜单栏(鼠标右键或快捷键shift+f10)之后按i 资料: 1.如何为windows 10添加右键context menu item https://stackoverflow.com/ques ...