1009: [HNOI2008]GT考试

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 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

4 3 100
111

Sample Output

81

如果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 123
2351237
*/

bzoj 1009: [HNOI2008]GT考试(dp+kmp+矩阵快速幂)相关推荐

  1. BZOJ 1009: [HNOI2008]GT考试(kmp+dp+矩阵优化)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1009 题意: 思路: 真的是好题啊! 对于这种题目,很有可能就是dp,$f[i][j]$表示分析到第 ...

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

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

  3. BZOJ 1009 [HNOI2008]GT考试

    1009: [HNOI2008]GT考试 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2154  Solved: 1327 [Submit][Sta ...

  4. BZOJ 1009:[HNOI2008]GT考试

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1009 大意:给一个长度不大于20的数字串,求长度为N(10^9)的所有数字串中不包含该串 ...

  5. BZOJ[1009] [HNOI2008]GT考试

    了了已久的心结 f[i][j]表示到第i为,长度为j的后缀与不吉利数字的前缀相同,其实这个和一些期望概率的DP类似,利用a数组记录当前j在加上不同的数字之后,可以分别转移至那些状态,用KMP处理一下, ...

  6. HNOI2008 GT考试 (KMP + 矩阵乘法)

    传送门 这道题目的题意描述,通俗一点说就是这样:有一个长度为n的数字串(其中每一位都可以是0到9之间任意一个数字),给定一个长度为m的模式串,求有多少种情况,使得此模式串不为数字串的任意一个子串.结果 ...

  7. 【POJ - 3744】Scout YYF I(概率dp,矩阵快速幂优化dp)

    题干: 题目大意: 在一条不满地雷的路上(无限长),你现在的起点在1处.在N个点处布有地雷,1<=N<=10.地雷点的可能坐标范围:[1,100000000]. 每次前进p的概率前进一步, ...

  8. [CSP-S模拟测试]:涂色游戏(DP+组合数+矩阵快速幂)

    题目描述 小$A$和小$B$在做游戏. 他们找到了一个$n$行$m$列呈网格状的画板.小$A$拿出了$p$支不同颜色的画笔,开始在上面涂色.看到小$A$涂好的画板,小$B$觉得颜色太单调了,于是把画板 ...

  9. BZOJ.4180.字符串计数(后缀自动机 二分 矩阵快速幂/倍增Floyd)

    题目链接 先考虑 假设S确定,使构造S操作次数最小的方案应是:对T建SAM,S在SAM上匹配,如果有S的转移就转移,否则操作数++,回到根节点继续匹配S.即每次操作一定是一次极大匹配. 简单证明:假设 ...

最新文章

  1. Unity The Type Matching Rule
  2. bogofilter 使用
  3. php 命名空间 create_function,PHP create_function()注入命令执行漏洞
  4. 下载kaggle数据集的小妙招
  5. linux中查找文件属于那个软件包的方法
  6. 新来乍到,谢谢大家捧场
  7. MacVim配置目录树
  8. DataFrame列转json以及json转DataFrame列
  9. neo4j jdbc中文乱码
  10. 刘德华2007新歌《一》歌词及在线试听地址
  11. python one class svm_sklearn例程:OneClassSVM物种分布建模
  12. pandas计算excel两列的日期差
  13. 英语六级高频词汇速记 + 2019-12-1听力 Day07
  14. 51单片机入门——动态数码管显示详解
  15. 2020-2021考研南京大学软件学院学习经验分享(英语90,842自命题110+)
  16. 端口隔离的原理与配置
  17. 北京高新技术企业申报新增要求及解决办法
  18. 商界大佬们惊人一致的六大成功密码!
  19. UNI-APP_在uni-app中引入和使用uViewUI
  20. My命名空间——VB.NET

热门文章

  1. python编程入门教程下载-《Python编程从入门到精通》PDF高清完整版-PDF下载
  2. python项目开发实例-《Python项目案例开发从入门到实战》PDF版百度网盘
  3. 自学python能干什么-普通人学Python能干什么?老男孩Python入门
  4. python零基础好学吗-Python零基础好学吗?零基础如何学习Python?
  5. 国家机构评测主流电视:长虹人工智能语音识别第一
  6. IBM语音识别能力逼近人类水平,获深度学习巨头Yoshua Bengio盛赞
  7. 栈中对象定位的方式(句柄池,直接引用)
  8. 【linux笔记】linux权限命令
  9. 【java笔记】基本类型与字符串之间的转换
  10. java 对象赋值给scala_将Scala变量转换为Java对象… varargs