码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1009 [HNOI2008]GT考试

时间:2018-01-06 21:06:44      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:next数组   using   set   ace   str   ext   数字   void   表示   

KMP+矩阵快速幂+DP;

按顺序处理准考证号每一位,
设f[i][j]表示:准考证号前i位中 后j位与不吉利数的前j位相同时,前i位的方案数 
那么答案ans=f[n][0]+f[n][1]+…+f[n][m-1]

状态转移:
f[i][j]只能由f[i-1][k]得到,相当于填完第i-1位后,将其后缀k(长为k的后缀)后面新添一位num,之后这个i位数的 与不吉利数前缀相同的最长后缀是j

转移方程: f[i][j] = f[i-1][0]*pre[0][j] + f[i-1][1]*pre[1][j] + f[i-j][2]*pre[2][j] + ...... f[i-1][m-1]*pre[m-1][j];(没有f[i-1][m]是因为这种情况是不合法的)

那么怎么求出这样的处理呢? 使用kmp的next数组,从i位置开始,然后开始枚举第i+1位的数字开始向后匹配,然后找到可以匹配的最大的那个位置,基本写法参照kmp的匹配。每找到某一个位置,把那个位置的+1即可。

因为我们匹配中尽量让不吉利的串长,所以匹配最大的那个位置(熟悉next数组应该很容易理解)

观察式子是个矩阵快速幂,可以log求出答案。

By:大奕哥

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int nex[25];int n,m,mod;
 4 void setnex(char s[],int n)
 5 {
 6     int j=0;nex[1]=j;
 7     for(int i=2;i<=n;++i)
 8     {
 9         while(j&&s[i]!=s[j+1])j=nex[j];
10         if(s[i]==s[j+1])++j;
11         nex[i]=j;
12     }
13 }
14 struct node{
15     int n,m,s[25][25];
16     node(){
17         n=m=0;memset(s,0,sizeof(s));
18     }
19 };
20 node mul(node a,node b)
21 {
22     node c;c.n=a.n;c.m=b.m;
23     for(int k=0;k<a.m;++k)
24     for(int i=0;i<a.n;++i)
25     for(int j=0;j<b.m;++j)
26     {
27         c.s[i][j]=(c.s[i][j]+a.s[i][k]*b.s[k][j]%mod)%mod;
28     }
29     return c;
30 }
31 node qmod(node a,int x)
32 {
33     node c;c.n=a.n;c.m=a.m;
34     for(int i=0;i<a.n;++i)c.s[i][i]=1;
35     while(x)
36     {
37         if(x&1)c=mul(c,a);
38         x>>=1;a=mul(a,a);
39     }
40     return c;
41 }
42 int main()
43 {
44     char s[25];int k;
45     scanf("%d%d%d",&n,&m,&k);mod=k;
46     scanf("%s",s+1);setnex(s,m);
47     node p,ans;p.n=p.m=m;
48     for(int i=0;i<m;++i)
49     {
50         for(char j=0;j<=9;++j)
51         {
52             int k=i;
53             while(k&&s[k+1]!=j)k=nex[k];
54             if(s[k+1]==j)p.s[i][k+1]++;
55             else p.s[i][0]++;
56         }
57     }
58     ans.n=1,ans.m=m;
59     ans.s[0][0]=1;
60     ans=mul(ans,qmod(p,n));
61     int sum=0;
62     for(int i=0;i<m;++i)sum=(sum+ans.s[0][i])%mod;
63     printf("%d",sum);
64     return 0;
65 }

 

BZOJ1009 [HNOI2008]GT考试

标签:next数组   using   set   ace   str   ext   数字   void   表示   

原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8215115.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!