BZOJ_1009_[HNOI2008]_GT考试_(动态规划+kmp+矩阵乘法优化+快速幂)

描述



http://www.lydsy.com/JudgeOnline/problem.php?id=1009

字符串全部由0~9组成,给出一个串s,求一个长度为n的串,不包含s的种类有多少.

分析



第一眼以为是组合.然后更滑稽的是用错误的方法手算样例居然算出来是对的...我数学是有多差...

题解也是看了好半天,有点难理解.

感觉PoPoQQQ神犇讲得还是比较清楚的.传送门:http://blog.csdn.net/popoqqq/article/details/40188173

我们用dp[i][j]表示 : 长度为i的串, 其长度为j的后缀 与 s长度为j的前缀 完全匹配的种类数.

这样的话最后的答案就是ans=sigma{dp[n][i]}(0<=i<m).

这里还有一个二维的a数组,就这个比较难解释...

dp[i][y]可以由dp[i-1][x]转移而来,那么匹配的s的前缀由长度x变成了长度y,a[x][y]表示的就是在结尾添加一个字符后,匹配长度从x变成y,这样的字符有多少种.

那么 dp[i][y]=sigma{dp[i-1][x]*a[x][y]}.

这个可以用矩阵乘法算.

那么a数组怎么求呢?用kmp.

a[x][y]表示的是前缀匹配长度由x变成了y的种类数,那么从每一位i开始匹配,如果匹配到了j,那么a[i][j+1]++(数组从0开始,第i位之前匹配了i个,匹配到第j位,应该是j+1个).

p.s.我好菜呀...

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 const int maxn=100+5;
 5 int n,m,p,ans;
 6 char str[maxn];
 7 int f[maxn];
 8
 9 struct matrix{
10     int x[25][25];
11     matrix(){ memset(x,0,sizeof x); }
12     int * operator [] (int id){ return x[id]; }
13 }dp,a;
14 void operator *= (matrix &x,matrix &y){
15     matrix z;
16     for(int i=0;i<m;i++)for(int j=0;j<m;j++)for(int k=0;k<m;k++)
17         z[i][j]+=x[i][k]*y[k][j], z[i][j]%=p;
18     x=z;
19 }
20 void kmp(){
21     for(int i=1;i<m;i++){
22         int j=f[i];
23         while(j&&str[i]!=str[j]) j=f[j];
24         f[i+1]=str[i]==str[j]?j+1:0;
25     }
26     for(int i=0;i<m;i++)for(char k=‘0‘;k<=‘9‘;k++){
27         int j=i;
28         while(j&&k!=str[j]) j=f[j];
29         if(k==str[j]) a[i][j+1]++;
30         else a[i][0]++;
31     }
32 }
33 void quick_power(int y){
34     for(;y;a*=a,y>>=1) if(y&1) dp*=a;
35 }
36 int main(){
37     scanf("%d%d%d",&n,&m,&p);
38     scanf("%s",str);
39     kmp();
40     dp[0][0]=1;
41     quick_power(n);
42     for(int i=0;i<m;i++) ans+=dp[0][i], ans%=p;
43     printf("%d\n",ans);
44     return 0;
45 }

1009: [HNOI2008]GT考试

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

Source

时间: 2025-01-07 03:22:09

BZOJ_1009_[HNOI2008]_GT考试_(动态规划+kmp+矩阵乘法优化+快速幂)的相关文章

[BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】

题目链接:BZOJ - 1009 题目分析 题目要求求出不包含给定字符串的长度为 n 的字符串的数量. 既然这样,应该就是 KMP + DP ,用 f[i][j] 表示长度为 i ,匹配到模式串第 j 位的字符串个数,然后转移就是可以从第 j 位加上一个字符转移到另一个位置. 然而..我并没有写过KMP + DP,我觉得还是写AC自动机+DP比较简单..于是,尽管只有一个模式串,我还是写了AC自动机+DP. 然后就是建出AC自动机,f[i][j] 表示长度为 i ,走到节点 j 的字符串的个数.

矩阵乘法、快速幂

1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 #include <cstring> 5 using namespace std; 6 // 矩阵的STL实现 7 typedef vector<int> vec; 8 typedef vector<vec> mat; 9 typedef long long ll; 10 const int MOD = 10

poj3613:Cow Relays(倍增优化+矩阵乘法floyd+快速幂)

Cow Relays Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7825   Accepted: 3068 Description For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout

bzoj 3240 矩阵乘法+十进制快速幂

首先,构造出从f[][i]->f[][i+1]的转移矩阵a,和从f[i][m]->f[i+1][1]的转移矩阵b, 那么从f[1][1]转移到f[n][m]就是init*(a^(m-1)*b)^(n-1)*(a^(m-1)). 然后用用十进制快速幂(因为输入用的是10进制,这样就避免了高精度除法). 第一次写十进制快速幂,大概的思想是维护当前位是1-9的要乘的矩阵,然后再通过这9个矩阵自己转移. 1 /**********************************************

bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化

3240: [Noi2013]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 613  Solved: 256[Submit][Status] Description 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式: F[1][1]=1F[i,j]=a*F[i][j-1]+

【HDOJ5950】Recursive sequence(矩阵乘法,快速幂)

题意:f[1]=a,f[2]=b,f[i]=2f[i-2]+f[i-1]+i^4(i>=3),多组询问求f[n]对2147493647取模 N,a,b < 2^31 思路:重点在于i^4的处理 对于i转移矩阵中可以记录下它的0,1,2,3,4次项 i的幂又可以由i-1的幂运算得出,最后推出的系数是二项式展开的系数 试试新的矩乘模板 1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #inc

用矩阵乘法优化递推

(有关矩阵乘法的基本规则请自行搜索) 引例:求斐波那契数列的第 n 项 mod 1000000007 的值,n <= 1018. 分析:斐波那契数列的递推式为 f(n) = f(n-1)+f(n-2),直接循环求出 f(n) 的时间复杂度是 O(n),对于题目中的数据范围显然无法承受.很明显我们需要对数级别的算法. 由于 f(n) = 1*f(n-1) + 1*f(n-2) 这样的形式很类似于矩阵的乘法,所以我们可以先把这个问题复杂化一下,将递推求解 f(n) 与 f(n-1) 的过程看作是某两

2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)

题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据是不可能会有的,而我们一开始一直在想极端数据能接受的方法......后来看了鹏哥的做法,就是把是0的地方都跳过就可以了,用矩阵保存前一个非0数的位置是多少.二师兄给我看了一个代码,人家根本没用别的优化,直接将最里层k的循环提到了最外层,然后就AC了,对此我表示无语. 1 #include <cstd

斐波那契优化 快速幂+矩阵乘法

题目:你能求得第n个斐波那契数吗?0<n<maxlongint 由于结果太大,输出的结果mod32768 思路:一般的求斐波那契数列的方法有递归,动归,或者用滚动优化,但是空间复杂或者时间复杂度都太高了,现在有一种用矩阵加快速幂的优化算法,可以让时间复杂度维持在logn. 具体的 初始化一个2×2的矩阵,初始值为{1,0,0,1} 则分别代表{a2,a1,a1,a0},把此矩阵平方后得到{2,1,1,0}分别代表{a3,a2,a2,a1}如此下去,便可以得到规律,其实这个算法主要就是优化在快速