• 【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写起来怎么那么长,搞的码风丑死啦

  • 相关阅读:
    项目中见过最好的创建树的过程
    验证Math.random()函数产生的是均匀分布的数值
    一道LINQ题,可以瞅一眼
    EntityFramework5的性能到底提高在哪里了?
    如何很好的使用Linq的Distinct方法
    EntityFramework开发三种工作流简介
    实现自动抛弃当前数据库上下文的模块。支持各种ORM框架并存
    SPS中WebPart加缓存
    交流与设计,项目管理中必备的!
    redmine 安装roadmap 插件
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5453407.html
Copyright © 2020-2023  润新知