[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+矩阵快速幂)的更多相关文章

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

    题目链接 设f[i][j]为当前是第i位考号.现在匹配到第j位(已有j-1位和A[]匹配)的方案数 因为假如当前匹配j位,如果选择的下一位与A[j+1]不同,那么新的匹配位数是fail[j]而不是0, ...

  2. bzoj1009: [HNOI2008]GT考试 ac自动机+矩阵快速幂

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

  3. [BZOJ1009] [HNOI2008] GT考试 (KMP & dp & 矩阵乘法)

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

  4. $bzoj1009-HNOI2008$ $GT$考试 字符串$dp$ 矩阵快速幂

    题面描述 阿申准备报名参加\(GT\)考试,准考证号为\(N\)位数\(x_1,x_2,...,x_n\ (0\leq x_i\leq 9)\),他不希望准考证号上出现不吉利的数字. 他的不吉利数字\ ...

  5. 【BZOJ-1009】GT考试 KMP+DP+矩阵乘法+快速幂

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

  6. bzoj 1009: [HNOI2008]GT考试【kmp+dp+矩阵快速幂】

    看n和k的范围长得就很像矩阵乘法了 设f[i][j]表示到第i个位置的后缀最长匹配目标串的j位.转移的话显然是枚举0~9,然后选择f[i+1]中能被他转移的加起来,需要用到next数组.然后构造矩阵的 ...

  7. [BZOJ1009][HNOI2008]GT考试(KMP+DP)

    [不稳定的传送门 Solution dp[i][j]表示前i个字符当前匹配到不吉利串的第j个,即当前方案的后缀等于不吉利串前缀 然而由于n过大,不能直接转移,用矩阵优化 Code #include & ...

  8. [bzoj1009](HNOI2008)GT考试 (kmp+矩阵快速幂加速递推)

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

  9. 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 ...

随机推荐

  1. Win 7无法安装Microsoft .NET Framework 4.6.2

    造冰箱的大熊猫@cnblogs 2018/9/6 在Windows 7 64位计算机上安装某个软件时,安装程序提示需先安装Microsoft .NET Framework 4.6.2.本来以为小事一桩 ...

  2. 51 Nod 线段最长重叠部分

    1091 线段的重叠  基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 X轴上有N条线段,每条线段包括1个起点和终点.线段的重叠是这样来算的,[10 20]和[12 ...

  3. Aragorn's Story

    A - Aragorn's Story 直接套 线段树+树剖 板子 代码: // Created by CAD on 2019/8/12. #include <bits/stdc++.h> ...

  4. python学习之路(6)

    使用dict和set Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度. 举个例子,假设要根 ...

  5. Java NIO学习

    Java NIO(转自:http://www.iteye.com/magazines/132-Java-NIO#585) Java NIO提供了与标准IO不同的IO工作方式: Channels,Buf ...

  6. Running .sh scripts in Git bash

    Running .sh scripts in Git bash Let's say you have a script script.sh. To run it (using Git Bash), y ...

  7. redis扫描特定keys脚本,可避免阻塞,不影响线上业务

    #!/bin/sh ## 该脚本用来查询redis集群中,各个实例当中特定前缀的key,对应只需要修改redis的其中一个实例的 host和port## 脚本会自动识别出该集群的所有实例,并查出对应实 ...

  8. leetcode 172. Factorial Trailing Zeroes(阶乘的末尾有多少个0)

    数字的末尾为0实际上就是乘以了10,20.30.40其实本质上都是10,只不过是10的倍数.10只能通过2*5来获得,但是2的个数众多,用作判断不准确. 以20的阶乘为例子,造成末尾为0的数字其实就是 ...

  9. dvm 的进程和 Linux 的进程, 应用程序的进程是否为同一个概念?

    dvm 指 dalvik 的虚拟机. 每一个 Android 应用程序都拥有一个独立的 Dalvik 虚拟机实例,应用程序都在它自己的进程中运行.而每一个 dvm 都是在 Linux 中的一个进程,所 ...

  10. Jenkins发布

    右键查看图片显示全图