bzoj1009 [HNOI2008] GT考试 矩阵乘法+dp+kmp

1009: [HNOI2008]GT考试

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 4542  Solved: 2815
[Submit][Status][Discuss]

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

HINT

矩阵乘法的题题解写起来都十分麻烦。。

而且很多东西只能意会。。

f[i , j]表示前 i 个准考证号匹配到不吉利串第 j 个的方案

然后你需要把一个答案矩阵f[i , j]转移到f[i+1 , j]

举个例子,样例,比如当前匹配到了第2位,也就是说前 i 位的结尾是11

对于第 i+1 个字符,如果是 1 的话,接着匹配到不吉利串第 3 位,不是 1 的话就匹配到第 0 位了

也就是说前 i 位匹配到了不吉利串 j 位,加入 i+1 这个字符,有不同情况,有一些会转移到j+1,一些会转移到其他的,写成一些形如f[i+1 , k] += f[i , j]的式子……

f[i+1 , 3] += f[i , 2]

f[i+1 , 0] += f[i , 2]

即枚举i+1可能出现的字符,然后看n个f[i , j]分别转移到哪去,就在转移矩阵的这个转移路径上+1

按照这个思路用kmp写出转移矩阵,事实上暴力应该就行了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 inline int read()
 6 {
 7     char ch=getchar();
 8     int f=1,x=0;
 9     while(!(ch>=‘0‘&&ch<=‘9‘)){if(ch==‘-‘)f=-1;ch=getchar();}
10     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+(ch-‘0‘);ch=getchar();}
11     return x*f;
12 }
13 int n,m,mod;
14 int p[25];
15 char ch[25];
16 int a[25][25],b[25][25];
17 void mul(int a[25][25],int b[25][25],int ans[25][25])
18 {
19     int tmp[25][25];
20     for(int i=0;i<m;i++)
21         for(int j=0;j<m;j++)
22         {
23             tmp[i][j]=0;
24             for(int k=0;k<m;k++)
25                 tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
26         }
27     for(int i=0;i<m;i++)
28         for(int j=0;j<m;j++)
29             ans[i][j]=tmp[i][j];
30 }
31 int main()
32 {
33     n=read();m=read();mod=read();
34     scanf("%s",ch+1);
35     int j=0;
36     for(int i=2;i<=m;i++)
37     {
38         while(j>0&&ch[j+1]!=ch[i])j=p[j];
39         if(ch[j+1]==ch[i])j++;
40         p[i]=j;
41     }
42     for(int i=0;i<m;i++)
43        for(int j=0;j<=9;j++)
44        {
45                int t=i;
46             while(t>0&&ch[t+1]-‘0‘!=j)
47                 t=p[t];
48             if(ch[t+1]-‘0‘==j)t++;
49             if(t!=m)b[t][i]=(b[t][i]+1)%mod;
50        }
51     for(int i=0;i<m;i++)
52         a[i][i]=1;
53     while(n)
54     {
55         if(n&1)mul(a,b,a);
56         mul(b,b,b);
57         n>>=1;
58     }
59     int sum=0;
60     for(int i=0;i<m;i++)
61         sum=(sum+a[i][0])%mod;
62     printf("%d",sum);
63     return 0;
64 }

原文地址:https://www.cnblogs.com/fengzhiyuan/p/8530477.html

时间: 2024-11-05 17:19:43

bzoj1009 [HNOI2008] GT考试 矩阵乘法+dp+kmp的相关文章

BZOJ1009: [HNOI2008]GT考试 矩阵快速幂+kmp+dp

这个题你发现打暴力的话可以记忆化搜素加剪枝,那么意味着可以递推,我们搜的话就是1010^9我们就往下匹配遇到匹配成功就return,那么我们可以想一下什么决定了状态,我们考虑kmp的过程,对于我们目前匹配到的距离,下一次在匹配时不会用他之后的字符,那么只要我们知道匹配到的距离和已匹配长度就行了,那么我们考虑状态的转移,我们由于要像kmp那样匹配于是我们只要知道在匹配到k位时往下走一个数时匹配到哪,算出a[k][j](在k时到j的方案数),那么新的f[i][j]=∑f[i-1][k]*a[k][j

BZOJ1009 [HNOI2008]GT考试 矩阵

题目 [bzoj1009][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位的数. 100%数据N<=10^9,M<=20,K<=1000 40%数据N<

[矩阵乘法][DP]Vijos1067 Warcraft III 守望者的烦恼

题目梗概 n个单位的路程,主角每次最多可以走k个单位(也就是每次可以走1-k个单位),问最后到第n个监狱的方法数. 思考 DP转移方程并不难推导: dp[i]表示第i个监狱的方法数 $dp\left [ i \right ] = dp\left [ i-1 \right ] + dp\left [ i-2 \right ]\cdots \cdots + dp\left [ i-k-1 \right ]$ 但是这个n有点太大了,所以我们需要对DP方程进行优化. 仔细观察转移方程会发现,每次都是加上

【BZOJ4870】组合数问题 [矩阵乘法][DP]

组合数问题 Time Limit: 10 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description Input 第一行有四个整数 n, p, k, r,所有整数含义见问题描述. Output 一行一个整数代表答案. Sample Input 2 10007 2 0 Sample Output 8 HINT 1 ≤ n ≤ 10^9, 0 ≤ r < k ≤ 50, 2 ≤ p ≤ 2^30 − 1 Solution 首先,不难发

JZYZOJ 1542 [haoi2015]str 矩阵乘法 dp

http://172.20.6.3/Problem_Show.asp?id=1542 dp+矩阵乘法思路hin好想,对于我这种题目稍微学术就几乎什么也不会的人来说唯一的难点在于读题,因为一心想着划水题目没有看清楚,样例wa了一会最后仔细读题发现自己g的操作看错了,非常智障了 代码 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #inclu

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

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

BZOJ1009 HNOI2008 GT考试 一般DP+矩阵乘法+KMP

题意:给定一个长度为M的字符串A,求长度为N的字符串中,子串中不包含A的字符串的数量,其中字符串仅由‘0’-‘9’组成. 题解:设f[i][j]=长度为i最后几位能匹配A的前j个字符的字符串种数,那么每往后添加一个字符,能转移到的位置通过KMP的Next数组很轻松就能找到.那么我们就能构造出来一个矩阵,a[i][j]=1表示可以通过在A[i]后面加一个字符,使得A[1]-A[j]成为原有字符串的子串.快速幂优化后答案就是f[N][0]+……+f[N][M-1] #include <cstdio>

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

[不稳定的传送门 Solution dp[i][j]表示前i个字符当前匹配到不吉利串的第j个,即当前方案的后缀等于不吉利串前缀 然而由于n过大,不能直接转移,用矩阵优化 Code #include <cstdio> #include <algorithm> #include <cstring> using namespace std; char s[120]; int n,m,mo,nex[120]; inline int read(){ int x=0,f=1;cha

bzoj1009 [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位的数. 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6 O