bzoj1009 GT考试 (kmp+矩阵优化dp)

设f[i][j]是到第i位 已经匹配上了j位的状态数 然后通过枚举下一位放0~9,可以用kmp处理出一个转移的矩阵

然后就可以矩阵快速幂了

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxm=22;
 7
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();}
11     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
12     return x*neg;
13 }
14
15 int N,M,K,trans[maxm][maxm],ans[maxm][maxm],tmp[maxm][maxm],fail[maxm];
16 char x[maxm];
17
18 inline void mul(int a[][maxm],int b[][maxm]){
19     for(int i=0;i<M;i++){
20         for(int j=0;j<M;j++){
21             tmp[i][j]=0;
22             for(int k=0;k<M;k++){
23                 tmp[i][j]+=a[i][k]*b[k][j],tmp[i][j]%=K;
24             }
25         }
26     }
27 }
28
29 inline void modp(int b){
30     while(b){
31         if(b&1) mul(ans,trans),memcpy(ans,tmp,sizeof(ans));
32         mul(trans,trans),memcpy(trans,tmp,sizeof(tmp));
33         b>>=1;
34     }
35 }
36
37 int main(){
38     //freopen("","r",stdin);
39     int i,j,k;
40     N=rd(),M=rd(),K=rd();
41     scanf("%s",x+1);
42     for(i=2,j=0;i<=M;i++){
43         while(j&&x[i]!=x[j+1]) j=fail[j];
44         if(x[i]==x[j+1]) j++;
45         fail[i]=j;
46     }
47     for(i=0;i<M;i++){
48         for(j=‘0‘;j<=‘9‘;j++){
49             int k=i;
50             while(k&&j!=x[k+1]) k=fail[k];
51             if(j==x[k+1]) k++;
52             if(k<M) trans[i][k]++;
53         }
54     }
55     ans[0][0]=9,ans[0][1]=1;
56     modp(N-1);
57     int p=0;
58     for(i=0;i<M;i++) p+=ans[0][i];
59     printf("%d\n",p%K);
60     return 0;
61 }

原文地址:https://www.cnblogs.com/Ressed/p/9887244.html

时间: 2024-10-29 19:09:56

bzoj1009 GT考试 (kmp+矩阵优化dp)的相关文章

[HNOI2008][bzoj1009] GT考试 [KMP+矩阵快速幂]

题面 传送门 思路 首先,如果$n$和$m$没有那么大的话,有一个非常显然的dp做法: 设$dp[i][j]$表示长度为i的字符串,最后j个可以匹配模板串前j位的情况数 那么显然,答案就是$\sum_{i=0}^{m-1}dp[n][i]$了 转移过程则需要用一个辅助数组:令$g[i][j]$表示模板串的前缀$i$可以转移到前缀$j$的方法数(注意它可能可以转移到很多个串) 辅助数组的生成可以用next数组来推(模板串太短,其实暴力也是可以的) 那么$dp[i+1][k]=dp[i][j]*g[

题解: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 3120 矩阵优化DP

我的第一道需要程序建矩阵的矩阵优化DP. 题目可以将不同的p分开处理. 对于p==0 || p==1 直接是0或1 对于p>1,就要DP了.这里以p==3为例: 设dp[i][s1][s2][r]为前i列,结尾为0的有s1行(0表示女生,1表示男生),结尾为01的有s2个,结尾为011的有n-s1-s2个,有r列全是1的方案数. 状态这么复杂,看起来一点也不能用矩阵优化,但我们可以将状态(s1,s2,r)hash成整数,然后建立状态之间的转移. 收获: 这种m超过10^7的一般都要用矩阵优化,如

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<=

Codeforces Round #341 (Div. 2) E. Wet Shark and Blocks(矩阵优化DP)

题目链接:点击打开链接 题意:给n个数作为一个块,有b个块,从其中若干个中选择数,每个块只能选一个数,最后组成一个数模x等于k的方法数. 思路:很容易想到这样一个DP方程 : 用dp[i][j]表示现在i位,余数是j.那么dp[i + 1][(j * 10 + k) % x] = dp[i][j] * cnt[k],k是指枚举放1~9中哪一位. 因为b特别大,显然要矩阵优化,知道了DP方程,其实矩阵的构造特别简单. 根据矩阵相乘的规则, 其实这个矩阵就是A[j][(j*10+a[k])%x]++

BZOJ1297 [SCOI2009]迷路 【矩阵优化dp】

题目 windy在有向图中迷路了. 该有向图有 N 个节点,windy从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. 现在给出该有向图,你能告诉windy总共有多少种不同的路径吗? 注意:windy不能在某个节点逗留,且通过某有向边的时间严格为给定的时间. 输入格式 第一行包含两个整数,N T. 接下来有 N 行,每行一个长度为 N 的字符串. 第i行第j列为'0'表示从节点i到节点j没有边. 为'1'到'9'表示从节点i到节点j需要耗费的时间. 输出格式 包含一个整数,可能的路径数

Codeforces 351C Jeff and Brackets 矩阵优化DP

题意:你要在纸上画一个长度为n * m的括号序列,第i个位置画左括号的花费是a[i % n], 画右括号的花费是b[i % n],问画完这个括号序列的最小花费.n <= 20, m <= 1e7 思路:如果不管n和m的限制,这个题很好做,设dp[i][j]是到i位置,平衡因子是j的花费,dp[i][j] = min(dp[i - 1][j - 1] + a[i], dp[i - 1][j + 1] + b[i]),但是这样n * m到2e8级别,这是我们无法承受的.不过,我们可以发现一个性质:

_bzoj1009 [HNOI2008]GT考试【矩阵加速dp】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1009 比较不错的一道题,令f(i, j)表示考号匹配到i位,后j位为不吉利串的前j位,那么对于每一个状态,都是上一个状态的线性组合,所以可以用矩阵来加速. #include <cstdio> #include <cstring> const int maxn = 1000000005, maxm = 25; int n, m, p, mtx[maxm][maxm], trie

「模拟8.21」山洞(矩阵优化DP)

暴力: 正解: 考虑循环矩阵,f[i][j]表示从i点到j点的方案数 我们发现n很小,我们预处理出n次的f[i][j] 然后在矩阵快速幂中,我们要从当前的f[i][j]*f[j][k]-->fir[i][j] 但是此时的循环为三层 我们考虑转移式子的意义在0-n次从i-j,在n+1到2×n转移至j 这样此时的j-k其实可以把他看作从0开始走j-k步本质上是一样的 然后还有一个特判,就不讲了 for(int j=0;j<n;++j) { ff[now][j]=(ff[now][j]+ff[las