zoukankan      html  css  js  c++  java
  • BZOJ 1009: [HNOI2008]GT考试( dp + 矩阵快速幂 + kmp )

    写了一个早上...就因为把长度为m的也算进去了...

    dp(i, j)表示准考证号前i个字符匹配了不吉利数字前j个的方案数. kmp预处理, 然后对于j进行枚举, 对数字0~9也枚举算出f(i, j)表示dp(x-1, j)对dp(x, i)的贡献.然后用矩阵快速幂就可以了. 时间复杂度O(M3logN + M)

    -------------------------------------------------------------------

    #include<bits/stdc++.h>
     
    using namespace std;
     
    const int maxn = 25;
     
    int fail[maxn], S[maxn], N, M, MOD;
     
    struct matrix {
    int n, m;
    int a[maxn][maxn];
    matrix(int _n = 0, int _m = 0):n(_n), m(_m) {
    memset(a, 0, sizeof a);
    }
    void unit() {
    for(int i = 0; i < n; i++)
       a[i][i] = 1;
    }
    matrix operator * (matrix o) {
    matrix ret(n, o.m);
    for(int i = 0; i < n; i++)
       for(int k = 0; k < m; k++)
           for(int j = 0; j < o.m; j++)
               ret.a[i][j] = (ret.a[i][j] + a[i][k] * o.a[k][j]) % MOD;
    return ret;
    }
    matrix operator = (matrix o) {
    for(int i = 0; i < n; i++)
       for(int j = 0; j < n; j++)
           a[i][j] = o.a[i][j];
    return *this;
    }
    matrix operator ^ (int k) {
    matrix ret(n, m), t = *this; ret.unit();
    for(; k; k >>= 1) {
    if(k & 1) ret = ret * t;
    t = t * t;
    }
    return ret;
    }
    };
     
    void kmp() {
    fail[0] = fail[1] = 0;
    for(int i = 1; i < M; i++) {
    int p = fail[i];
    while(p && S[i] != S[p]) p = fail[p];
    fail[i + 1] = S[i] == S[p] ? p + 1 : 0;
    }
    }
     
    int main() {
    scanf("%d%d%d", &N, &M, &MOD);
    for(int i = 0; i < M; i++) {
    char c = getchar();
    for(; !isdigit(c); c = getchar());
    S[i] = c - '0';
    }
    kmp();
    matrix Q(M, M);
    for(int i = 0; i < M; i++)
    for(int j = 0; j < 10; j++) {
    int p = i;
    while(p && S[p] != j) p = fail[p];
    if(S[p] == j) p++;
    Q.a[p][i]++;
    }
    matrix ans(M, 1);
    ans.a[0][0] = 1;
    ans = (Q ^ N) * ans;
    int tot = 0;
    for(int i = 0; i < M; i++)
       if((tot += ans.a[i][0]) >= MOD) tot -= MOD;
    printf("%d ", tot);
    return 0;
    }

    -------------------------------------------------------------------  

    1009: [HNOI2008]GT考试

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 2236  Solved: 1368
    [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位的数。 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6

    Output

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

    Sample Input

    4 3 100
    111

    Sample Output

    81

    HINT

    Source

  • 相关阅读:
    Curl Get请求&漏参数
    【Java基础】日期操作(返回当前日期&日期比较)
    【Java基础】生产者消费者模式
    [Groovy] 在Groovy中优雅的实现do while
    【转载】时间复杂度的度量
    [转载]Spring Cloud初探
    [Maven] 使用Maven管理多模块项目
    JS基础三
    JS基础部分(二)
    笔记不详细记录了,学完css之后做出下面分布的导航页
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4770610.html
Copyright © 2011-2022 走看看