BZOJ 1009 HNOI 2008 GT考试 递推+矩乘

1009: [HNOI2008]GT考试

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

Solution

如果n很小的话,可以直接做数位DP,但是现在n很大,需要用到矩乘。

设F[i][j]表示准考证号前i位中匹配到不吉利数串的第j个的方案数。

我们很容易发现,F数组存在一定的转移关系。

转移时考虑当前匹配到不吉利串的第i个,下一个数字填0~9时,转移到匹配到不吉利串的第j个,匹配过程可以KMP,这样就可以构造出转移矩阵。

Code

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5 #include <algorithm>
 6
 7 using namespace std;
 8
 9 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
10 #define mset(a, b) memset(a, b, sizeof(a))
11 const int maxn = 25;
12 int n, m, MOD;
13 char s[maxn];
14 int nxt[maxn];
15 struct Matrix
16 {
17     int mat[maxn][maxn];
18     Matrix() { mset(mat, 0); }
19     Matrix operator * (const Matrix &AI) const
20     {
21         Matrix ret;
22         REP(i, 0, m-1)
23             REP(j, 0, m-1)
24             {
25                 ret.mat[i][j] = 0;
26                 REP(k, 0, m-1) (ret.mat[i][j] += mat[i][k]*AI.mat[k][j]) %= MOD;
27             }
28         return ret;
29     }
30 }A, B;
31
32 int main()
33 {
34     scanf("%d %d %d", &n, &m, &MOD);
35     scanf("%s", s+1);
36     int j = 0; nxt[1] = 0;
37     REP(i, 2, m)
38     {
39         while (j > 0 && s[j+1] != s[i]) j = nxt[j];
40         if (s[j+1] == s[i]) j ++;
41         nxt[i] = j;
42     }
43     REP(i, 0, m-1)
44         REP(j, 0, 9)
45         {
46             int t = i;
47             while (t > 0 && s[t+1]-‘0‘ != j) t = nxt[t];
48             if (s[t+1]-‘0‘ == j) t ++;
49             if (t != m) B.mat[t][i] = (B.mat[t][i]+1)%MOD;
50         }
51     REP(i, 0, m-1) A.mat[i][i] = 1;
52     while (n > 0)
53     {
54         if (n&1) A = A*B;
55         B = B*B;
56         n >>= 1;
57     }
58     int ans = 0;
59     REP(i, 0, m-1) ans = (ans+A.mat[i][0])%MOD;
60     printf("%d\n", ans);
61     return 0;
62 }

时间: 2024-08-29 18:47:40

BZOJ 1009 HNOI 2008 GT考试 递推+矩乘的相关文章

BZOJ 1009 HNOI 2008 GT考试 AC自动机+矩阵乘法

题目大意:给出一个不能出现的字符串,问长度为k的字符串有多少种. 思路:用给定串建立一个AC自动机(或者KMP随便了),然后跑矩阵乘法就行了. CODE: #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int k,length,p; char s[MAX]; in

BZOJ 1089 严格n元树 (递推+高精度)

题解:用a[i]表<=i时有几种树满足度数要求,那么这样就可以递归了,a[i]=a[i-1]^n+1.n个节点每个有a[i-1]种情况,那么将其相乘,最后加上1,因为深度为0也算一种.那么答案就是a[n]-a[n-1].然后就是高精度的问题了,发现很久没有现码高精度没手感了,连高进度加法进位都出了些问题,需要特别注意. #include <cstdio> #include <cstring> #include <algorithm> using namespace

[补档][HNOI 2008]GT考试

题目 阿申准备报名参加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取余的结果. SAMPL

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

[BZOJ 1008] [HNOI 2008] 越狱

1008: [HNOI2008]越狱 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 5041  Solved: 2177[Submit][Status][Discuss] Description 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱 Input 输入两个整数M,N.1<=M<=10^8,1<=N<=10

[BZOJ 1010][HNOI 2008] 玩具装箱toy

比较基础的斜率优化DP详见以下2篇博客 http://www.cnblogs.com/proverbs/archive/2012/10/06/2713109.html http://blog.163.com/myq_952/blog/static/863906320112711750378/ 主要总结斜率优化时的步骤 1.证明较优决策点对后续状态影响的持续性 2.求斜率方程:一般化为左边是J,K,右边是I的形式 3.规定队列的维护规则 4.看决策是否又单调性,没有的话有应该怎样维护 本题的代码

BZOJ 1197 HNOI2006 花仙子的魔法 递推

题目大意:求n维空间下的m个球最多可以将空间分为多少个区域 VFK的题解: http://vfleaking.blog.163.com/blog/static/174807634201321193348312/ 自己看吧.... 我还在纠结零维空间内放入一个零维的球之后空间到底会被分成几份..... #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> us

BZOJ 1004 HNOI 2008 Cards Burnside引理

题目大意:给出一个置换群,求有多少种本质不同的染色方案. 思路:Burnside引理:置换群的等价类数目=所有置换的不动点数目的平均值. 有了这个引理,我们只需要求出所有不动点的数目求一个平均值就可以的到等价类的数目了. 要使一种染色的方案在一种置换的意义下是不动点,需要让这个置换的每个循环节中的颜色都相同.先求出所有置换的循环,然后用一个背包就可以初解了.最后乘法逆元搞一下除法. CODE: #define _CRT_SECURE_NO_DEPRECATE #include <cstdio>

BZOJ 1007 HNOI 2008 水平可见直线 计算几何+栈

题目大意:给出一些笛卡尔系中的一些直线,问从(0,+∞)向下看时能看到哪些直线. 思路:半平面交可做,但是显然用不上.类似于求凸包的思想,维护一个栈.先将所有直线按照k值排序,然后挨个压进去,遇到有前一个交点被挡住的话就先弹栈. 比较闹心的是去重.我的方法是压栈之前先去重,然后在处理. CODE: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #includ