• [BZOJ1009][HNOI2008]GT考试(KMP+DP+矩阵乘法)


    1009: [HNOI2008]GT考试

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

    [Submit][Status][Discuss]

    这题要是多模式串可能还容易看出来一些,discuss里有单串AC自动机做法,但是“单串AC自动机”不就是KMP吗。

    首先看数据范围猜是矩乘,然后有了显然的DP方程,就可以根据转移递推式上矩乘优化了。

    https://blog.csdn.net/jeremygjy/article/details/50779475

    递推式里的p(k,j)需要用KMP处理,仅当k<=j+1时值非零。

    注意矩阵只要从0~m-1,因为匹配m位的情况要全部去除。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     5 typedef long long ll;
     6 using namespace std;
     7 
     8 const int N=30;
     9 char s[N];
    10 int n,m,p,k,ans,nxt[N];
    11 struct M{ int a[N][N]; M(){ memset(a,0,sizeof(a)); } }f,res;
    12 
    13 void getnxt(){
    14     nxt[0]=nxt[1]=0;
    15     rep(i,2,m){
    16         for (k=nxt[i-1]; k && s[k+1]!=s[i]; k=nxt[k]);
    17         if (s[k+1]==s[i]) nxt[i]=k+1; else nxt[i]=0;
    18     }
    19 }
    20 
    21 void mul(M &a,M b){
    22     M c;
    23     rep(i,0,m-1) rep(j,0,m-1) rep(k,0,m-1) c.a[i][k]=(c.a[i][k]+a.a[i][j]*b.a[j][k])%p;
    24     rep(i,0,m-1) rep(j,0,m-1) a.a[i][j]=c.a[i][j];
    25 }
    26 
    27 M ksm(M a,int b){
    28     M c;
    29     rep(i,0,m-1) c.a[i][i]=1;
    30     for (; b; mul(a,a),b>>=1)
    31         if (b & 1) mul(c,a);
    32     return c;
    33 }
    34 
    35 int main(){
    36     freopen("bzoj1009.in","r",stdin);
    37     freopen("bzoj1009.out","w",stdout);
    38     scanf("%d%d%d",&n,&m,&p); scanf("%s",s+1);
    39     getnxt();
    40     rep(i,0,m-1){
    41         for (char j='0'; j<='9'; j++){
    42             for (k=i; k && s[k+1]!=j; k=nxt[k]);
    43             if (s[k+1]==j) f.a[i][k+1]=(f.a[i][k+1]+1)%p; else f.a[i][0]=(f.a[i][0]+1)%p;
    44         }
    45     }
    46     res.a[0][0]=1; mul(res,ksm(f,n));
    47     rep(i,0,m-1) ans=(ans+res.a[0][i])%p;
    48     printf("%d
    ",ans);
    49     return 0;
    50 }
  • 相关阅读:
    cgroup开机自启动
    QPS
    Linux shell脚本的字符串截取
    设计模式 java
    kafka基本介绍
    Vagrant安装配置
    SuperMap空间数据处理与制图操作短视频汇总
    SuperMap 三维产品资料一览表
    SuperMap GIS资料-----云与Web端技术资料集锦
    世界地图和主要国家的 JSON 文件
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8758321.html
Copyright © 2020-2023  润新知