bzoj 1009: [HNOI2008]GT考试(dp+kmp+矩阵快速幂)
来源:互联网 发布:单片机电子时钟原理图 编辑:程序博客网 时间:2024/05/29 04:24
1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3932 Solved: 2398
[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
Sample Output
如果n很小的话,显然直接dp就好了
dp[i][j]表示身份证号的前i个数,最后j个数和不吉利数的前j位相同的合法情况数
不过注意这里的j一定是要是最长前缀
例如不吉利数2351237, 当前身份证前9个数是888235123,那么这属于dp[9][6]而不是dp[9][2]
那么怎么转移呢
很好想到dp[i][j] = dp[i][j-1],但仍然不一定
还是不吉利数2351237,dp[i][3] = dp[i-1][2]+dp[i-1][6],为什么还要加个dp[i-1][6]呢?
因为235123后面接5之后变为2351235,原本能匹配长度为6的前缀,加上5之后刚好只能匹配长度为3的前缀了
而吉利数是2351235的话就不能加了,因为dp[i-1][6]后面接个5应该算在dp[i-1][7]中(可以匹配长度为7的前缀)!
所以dp[i][j] = ∑(dp[i-1][k]*p[k][j]) (0<=k<=m-1)
其中p[k][j]表示不吉利数前k个字符加上某个字符后最多能匹配不吉利数的前j个字符,问有多少种可添加字符
比如不吉利数2351237,p[6][3]==1因为235123后面接个5变为2351235,最多能匹配前三个字符235,
p[1][0]==8,因为2后面只要不接3就一定不是不吉利数的任何前缀
这也意味着一般来讲只有j==0的时候p[i][j]会大于1,其他时候要不是0要不是1
再举个例子:不吉利数1235123723构成的p[][]矩阵(行和列都是0到m-1即0到9)
9 1 0 0 0 0 0 0 0 0
8 1 1 0 0 0 0 0 0 0
8 1 0 1 0 0 0 0 0 0
8 1 0 0 1 0 0 0 0 0
9 0 0 0 0 1 0 0 0 0
8 1 0 0 0 0 1 0 0 0
8 1 0 0 0 0 0 1 0 0
7 1 0 0 1 0 0 0 1 0
8 1 0 0 0 0 0 0 0 1
8 1 0 0 0 0 0 0 0 0
上面p[][]矩阵的第一行刚好就是dp[1][i]!而dp[2][i] = ∑(dp[1][k]*p[k][j]) (0<=k<=m-1)
是不是很像矩阵乘法?所以最后答案就是矩阵p[][]自乘n次后第一行的和
至于如何求出p矩阵?kmp瞎搞搞就好了
#include<stdio.h>#include<string.h>int n, mod;typedef struct{int i, j;int a[32][32];void init(){memset(a, 0, sizeof(a));}void unit(){memset(a, 0, sizeof(a));for(i=1;i<=n;i++)a[i][i] = 1;}}Matrix;Matrix Jz;Matrix Powto(Matrix p, int k);Matrix Jjcf(Matrix p1, Matrix p2);int main(void){int k, p, q, i, ans, net[25];char str[25], j;while(scanf("%d%d%d", &k, &n, &mod)!=EOF){Jz.init();scanf("%s", str+1);memset(net, 0, sizeof(net));p = 0, q = 1, net[1] = 0;while(q<=n){if(p==0 || str[p]==str[q]){p++, q++;if(str[p]==str[q])net[q] = net[p];elsenet[q] = p;}elsep = net[p];}Jz.a[1][1] = 9, Jz.a[1][2] = 1;for(i=1;i<=n-1;i++){for(j='0';j<='9';j++){p = i+1;while(str[p]!=j && p!=0)p = net[p];Jz.a[i+1][p+1]++;}}Jz = Powto(Jz, k);ans = 0;for(i=1;i<=n;i++)ans = (ans+Jz.a[1][i])%mod;printf("%d\n", ans);}return 0;}Matrix Powto(Matrix p, int k){Matrix bg, E;E.unit();if(k==0)return E;if(k==1)return p;bg = Powto(p, k>>1);bg = Jjcf(bg, bg);if((k&1)==1)bg = Jjcf(bg, p);return bg;}Matrix Jjcf(Matrix p1, Matrix p2){Matrix pe;int i, j, k;memset(pe.a, 0, sizeof(pe.a));for(i=1;i<=n;i++){for(j=1;j<=n;j++){for(k=1;k<=n;k++)pe.a[i][j] = (pe.a[i][j]+p1.a[i][k]*p2.a[k][j])%mod;}}return pe;}/*10000 7 1232351237*/
- bzoj 1009: [HNOI2008]GT考试(dp+kmp+矩阵快速幂)
- BZOJ 1009: [HNOI2008]GT考试(DP+KMP失配+矩阵快速幂)
- BZOJ KMP+矩阵快速幂 1009: [HNOI2008]GT考试
- [KMP DP 矩阵快速幂加速] BZOJ 1009 [HNOI2008]GT考试
- BZOJ 1009: [HNOI2008]GT考试【KMP上DP+矩阵快速幂
- BZOJ 1009-GT考试(kmp+矩阵快速幂+DP)
- BZOJ 1009([HNOI2008]GT考试-KMP+矩阵加速Dp)
- 【BZOJ】1009 [HNOI2008]GT考试 KMP+DP+矩阵优化
- BZOJ 1009 GT考试 KMP+DP+矩阵快速幂
- [BZOJ 1009][HNOI2008]GT考试(KMP+线性齐次递推的矩阵加速?+DP)
- [KMP+矩阵快速幂加速]BZOJ 1009——[HNOI2008]GT考试
- BZOJ 1009: [HNOI2008]GT考试 AC自动机+矩阵快速幂
- [bzoj 1009] [HNOI2008]GT考试:DP,单串AC自动机,矩阵快速幂
- BZOJ 1009 HNOI2008 GT考试 KMP算法+矩阵乘法
- bzoj 1009: [HNOI2008]GT考试 KMP+矩阵乘法
- 【bzoj1009】[HNOI2008]GT考试 矩阵+kmp+DP
- [BZOJ]1009 [HNOI2008]GT考试(ac自动机+矩阵快速幂优化状态转移)
- 1009: [HNOI2008]GT考试 矩阵乘法优化DP+KMP
- bzoj4199[luoguP2178]品酒大会[noi2015] (后缀数组+并查集)
- SNMP实践
- 没有Bug的二分法
- linux debian8.2版本安装详细步骤(无图)
- ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据
- bzoj 1009: [HNOI2008]GT考试(dp+kmp+矩阵快速幂)
- DGUT oj(002)
- java继承
- Hibernate遇到的问题
- Visual Studio(VS2017)配置C/C++-PostgreSQL(9.6.3)完整开发环境
- [cv] Image Convolution and Edge Detection (2nd)
- 问题解决 错误 LNK2001 无法解析的外部符号 "public: __cdecl CvANN_MLP_TrainParams::~CvA
- 【剑指offer】面试题:跳台阶
- Android SQLite数据库