zoukankan      html  css  js  c++  java
  • 【BZOJ-1009】GT考试 KMP+DP+矩阵乘法+快速幂

    1009: [HNOI2008]GT考试

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

    Solution

    这个题非常的好

    开始看范围,$10^{9}$显然O(n)都不能做啊,但是又像数位DP,所以肯定要优化,能优化到O(n)以下的只有矩乘快速幂优化DP了

    实际上确实和数位DP非常累死,F[i][j]表示位数为i,最后匹配了j位的方案数,这样答案显然为$sum_{i=1}^{n}F[n][i]$

    考虑KMP的next数组,分类讨论一下,搞到矩阵上,然后快速幂一下搞搞

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    int n,m,p,next[110],an; char S[110];
    struct Matrixnode
    {
        int da[30][30];
        Matrixnode(){memset(da,0,sizeof(da));}
    }a; 
    Matrixnode Mul (Matrixnode A,Matrixnode B)
    {
        Matrixnode C;
        for (int i=0; i<m; i++)
            for (int j=0; j<m; j++)
                for (int k=0; k<m; k++)
                    C.da[i][j]=(C.da[i][j]+A.da[i][k]*B.da[k][j])%p;
        return C;
    }
    Matrixnode Pow (Matrixnode A,int x)
    {
        Matrixnode re;
        for (int i=0; i<m; i++) re.da[i][i]=1;
        for (int i=x; i; i>>=1,A=Mul(A,A))
            if (i&1) re=Mul(re,A);
        return re;
    }
    void KMP_prework()
    {
        for (int j=0,i=2; i<=m; i++)
            {
                while (j && S[i]!=S[j+1]) j=next[j];
                if (S[j+1]==S[i]) j++; next[i]=j;
            }
        for (int i=0; i<m; i++)
            for (int x,j=0; j<10; j++)
                {
                    x=i;
                    while (x && S[x+1]-'0'!=j) x=next[x];
                    if (j==S[x+1]-'0') a.da[i][x+1]++; else a.da[i][0]++;
                }
    }
    int main()
    {
        scanf("%d%d%d
    ",&n,&m,&p); scanf("%s",S+1);
        KMP_prework();
        Matrixnode ans; ans=Pow(a,n);
        for (int i=0; i<m; i++) an=(an+ans.da[0][i])%p;
        printf("%d
    ",an);
        return 0;
    }

    Matrixnode写起来怎么那么长,搞的码风丑死啦

  • 相关阅读:
    查看windows以前连过的wifi密码
    winscp可能的替代品?
    查看windows的进程启动参数
    Ubuntu Server 安全补丁、版本升级
    AtCoder Beginner Contest 217 题解
    F. Alice and Recoloring 1&2
    E. Bored Bakry
    C. Bakry and Partitioning
    2021牛客多校 第四场
    AES解密报Given final block not properly padded
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5453407.html
Copyright © 2011-2022 走看看