• 1009: [HNOI2008]GT考试


    1009: [HNOI2008]GT考试

    Time Limit: 1 Sec Memory Limit: 162 MB

    Description

    阿申准备报名参加GT考试,准考证号为N位数(X_1X_2....X_n(0 le X_i le 9)),他不希望准考证号上出现不吉利的数字.
    他的不吉利数学(A_1A_2...A_m(0 le A_i le 9))有M位,不出现是指(X_1X_2...X_n)中没有恰好一段等于(A_1A_2...A_m).(A_1)(X_1)可以为(0)

    Input

    第一行输入N,M,K.接下来一行输入M位的数.(N le 10^9, M le 20,K le 1000)

    Output

    阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.

    Sample Input

    4 3 100

    111

    Sample Output

    81

    解法

    此题其实有点像poj2778,不过此题其实简单一些。
    可以先用KMP求出可以从哪些状态转移一步到哪些状态。
    之后就是一道矩阵的经典题目,求出n步的方案数。

    #include <cstdio>
    int n,m,mod,a[25][25],b[25][25],c[25][25],nxt[25];
    char s[25];
     
    inline void mul(int x[25][25],int y[25][25]) {
        int i,j,k;
        for(i=0;i<m;++i)
            for(j=0;j<m;++j) {
                c[i][j]=0;
                for(k=0;k<m;++k)
                  c[i][j]=(c[i][j]+x[i][k]*y[k][j])%mod;
            }
        for(i=0;i<m;++i)
          for(j=0;j<m;++j)
            x[i][j]=c[i][j];
    }
     
    int main() {
        int i,j=0,t;
        for(scanf("%d%d%d%s",&n,&m,&mod,s+1),i=2;i<=m;++i) {
            while(j&&s[j+1]!=s[i])j=nxt[j];
            nxt[i]=((s[j+1]==s[i])?(++j):(j));
        }
        for(i=0;i<m;++i)
          for(j=0;j<10;++j) {
            for(t=i;t&&s[t+1]!=j+'0';t=nxt[t]);
            if(((s[t+1]==j+'0')?++t:t)^m) (++b[t][i]<mod)?1:b[t][i]=0;
          }
        for(i=0;i<m;++i) a[i][i]=1;
        while(n) {
            if(n&1) mul(a,b);
            mul(b,b);
            n>>=1;
        }
        int ans=0;
        for(i=0;i<m;++i) (ans+=a[i][0])<mod?1:ans-=mod;
        printf("%d
    ",ans);
        return 0;
    }
    

    Ps:其实hdu2243和poj2778与此题都相似,不过它们是在Tire树上建立矩阵。

  • 相关阅读:
    HashMap、ConcurrentHashMap红黑树实现分析
    分布式系统ID
    分布式事务
    LRU算法实现
    Redis 深入
    分库分表利器——sharding-sphere
    Java常用的八种排序算法
    浅析Tomcat
    Kafka
    如何选择分布式事务形态
  • 原文地址:https://www.cnblogs.com/cycleke/p/5943426.html
Copyright © 2020-2023  润新知