zoukankan      html  css  js  c++  java
  • BZOJ1009 [HNOI2008]GT考试

    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 }
  • 相关阅读:
    zabbix实现mysql数据库的监控(四)
    Redis高级进阶(一)
    Redis高级进阶(二)
    Redis的管理
    9.动态SQL
    8.Mapper动态代理
    7.属性名与查询字段名不相同
    6.单表的CRUD操作
    5.API详解
    4.主配置文件详解
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8215115.html
Copyright © 2011-2022 走看看