BZOJ 1009 【HNOI2008】 GT考试

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取余的结果.

  这道题一眼看去像是一道容斥dp,仔细思考后发现其实普通的dp就可以做了。

  我们令fi,j表示准考证号确定了前i位,其中最后一段已经和不吉利串匹配了j位的方案数。那么,显然我们只需要枚举每一位选什么数字即可。至于加了一位数字之后最后一段匹配了多少位,完全可以用kmp来解决。因为kmp算法中next数组的含义就是不为整个串前缀与后缀相等的不为的最大长度。

  但是,这样的复杂度是O(N*M^2)的。观察发现,M特别小,于是可以把转移矩阵预处理出来,使用矩阵快速幂优化即可。

  下面贴代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
 7
 8 using namespace std;
 9 typedef long long llg;
10
11 int n,m,k,nt[22],ans;
12 char s[22];
13 void gi(int &x){if(x>=k) x%=k;}
14 struct matrix{
15     int w[23][23];
16     matrix(){memset(w,0,sizeof(w));}
17     void fu(){for(int i=0;i<m;i++) w[i][i]=1;}
18     matrix operator * (const matrix &h)const{
19         matrix a;
20         for(int i=0;i<m;i++)
21             for(int j=0;j<m;j++)
22                 for(int k=0;k<m;k++)
23                     a.w[i][j]+=w[i][k]*h.w[k][j],gi(a.w[i][j]);
24         return a;
25     }
26 }A,Aa;
27
28 int getint(){
29     int w=0;bool q=0;
30     char c=getchar();
31     while((c>‘9‘||c<‘0‘)&&c!=‘-‘) c=getchar();
32     if(c==‘-‘) c=getchar(),q=1;
33     while(c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar();
34     return q?-w:w;
35 }
36
37 matrix mi(matrix a,int b){
38     matrix s; s.fu();
39     while(b){
40         if(b&1) s=s*a;
41         a=a*a; b>>=1;
42     }
43     return s;
44 }
45
46 int main(){
47     File("a");
48     n=getint(); m=getint(); k=getint();
49     scanf("%s",s+1);
50     for(int i=2,j=0;i<=m;i++){
51         while(j && s[j+1]!=s[i]) j=nt[j];
52         if(s[j+1]==s[i]) j++;
53         nt[i]=j;
54     }
55     for(int i=0,x;i<m;i++)
56         for(int j=0;j<=9;j++){
57             x=i;
58             while(x && s[x+1]-‘0‘!=j) x=nt[x];
59             if(s[x+1]-‘0‘==j) x++;
60             if(x<m) A.w[i][x]++;
61         }
62     Aa=mi(A,n);
63     for(int i=0;i<m;i++) ans+=Aa.w[0][i],gi(ans);
64     printf("%d",ans);
65 }
时间: 2024-10-11 02:41:11

BZOJ 1009 【HNOI2008】 GT考试的相关文章

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

原题描述: 阿申准备报名参加GT考试,准考证号为N位数 X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学A1A2...Am(0<=Ai& lt;=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0 分析: 吐槽:这道题的细节问题差点坑死我. 一开始这道题想了个DP,但是状态转移太恶心. 那我们换一个思路,先用KMP构造出A的一个自动机. 然后这道题就转化成了在自动机上跑啊跑,跑N条边都没跑

BZOJ 1009: [HNOI2008]GT考试 AC自动机+矩阵快速幂

经典题目了....虽然只有一个不能出现的字符串,但还是写了ac自动机 1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2051  Solved: 1257 [Submit][Status][Discuss] Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学A1A2...Am(0<=Ai<

BZOJ 1009: [HNOI2008]GT考试

1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 3437  Solved: 2110[Submit][Status][Discuss] Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字.他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2..

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

写了一个早上...就因为把长度为m的也算进去了... dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j)表示dp(x-1, j)对dp(x, i)的贡献.然后用矩阵快速幂就可以了. 时间复杂度O(M3logN + M) ------------------------------------------------------------------- #include<bits/stdc++.h>

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

1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MB 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<=

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

题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j 位的字符串个数,然后转移就是可以从第 j 位加上一个字符转移到另一个位置. 然而..我并没有写过KMP + DP,我觉得还是写AC自动机+DP比较简单..于是,尽管只有一个模式串,我还是写了AC自动机+DP. 然后就是建出AC自动机,f[i][j] 表示长度为 i ,走到节点 j 的字符串的个数.

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

题目大意:给定长度为m的数字串s,求不包含子串s的长度为n的数字串的数量 n<=10^9 光看这个O(n)就是挂 我们不考虑这个 令f[i][j]为长度为i的数字串中最后j位与s中的前j位匹配的方案数 比如当s为12312时 f[i][3]表示长度为i,以123结尾且不包含子串"12312"的方案数 a[x][y]为f[i-1][x]转移至f[i][y]的方案数 换句话说(可能描述不清楚) a[x][y]为s的长度为x的前缀加上一个数字后 后缀可以与最长长度为y的前缀匹配 这个数

BZOJ 1009 [HNOI2008]GT考试 AC自动机+矩阵乘法

题意:链接略 方法: AC自动机+矩阵乘法 解析: 和POJ 2778 一样的题. 大概的思路就是我们建AC自动机的时候需要注意如果某个点是一个串的结尾的话,那么下面的节点都要看成结尾节点. 然后按照AC自动机赋一下矩阵内部值就好了. 赋的矩阵代表从一个节点走一步走到另一个节点有多少方案. 然后经典模型,矩阵的n次方即可. 代码: #include <queue> #include <cstdio> #include <cstring> #include <ios

【矩阵乘】【KMP】【HNOI 2008】【bzoj 1009】GT考试

1009: [HNOI2008]GT考试 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 2230 Solved: 1364 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.接下

【刷题】BZOJ 3262 [HNOI2008]GT考试

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取余的