zoukankan      html  css  js  c++  java
  • bzoj 1009:[HNOI2008]GT考试

         这道题机房n多人好久之前就A了…… 我到现在才做出来……

         一看就是DP+矩阵乘法,但是一开始递推式推错了…… 正确的递推式应该是二维的……

      f[i][j] 表示第准考证到第 i 位匹配了 j 位的方案数

      f[i][j] = f[i][j-1] + f[i][k]  第k位可以转移到第 j 位

         这就需要枚举 当前位是什么, 同是还需要求一个关于m 的KMP 就可以了

      上代码:

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define M 25
    using namespace std;
    
    int n, m;
    long long f[M] = {0}, yu;
    long long a[M][M] = {0}, b[M][M] = {0}, c[M][M];
    int next[M] = {0};
    char s[M];
    
    void make_next()
    {
        int i = 0, j = -1;
        next[0] = -1;
        while (i < m-1)
            if (j == -1 || s[i] == s[j])
            {
                i++; j++;
                next[i] = j;
            }
            else j = next[j];
    }
    
    void cheng()
    {
        for (int i = 0; i < m; ++i)
            for (int j = 0; j <= m; ++j)
                c[i][j] = 0;
        for (int i = 0; i < m; ++i)
        for (int j = 0; j < m; ++j)
        for (int k = 0; k < m; ++k)
            c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % yu;
        swap(c, b);
    }
    
    void fan()
    {
        for (int i = 0; i < m; ++i)
            for (int j = 0; j <= m; ++j)
                c[i][j] = 0;
        for (int i = 0; i < m; ++i)
        for (int j = 0; j < m; ++j)
        for (int k = 0; k < m; ++k)
            c[i][j] = (c[i][j] + a[i][k] * a[k][j]) % yu;
        swap(c, a);
    }
    
    void mi(int n)
    {
        for (int i = 0; i < m; ++i)
                b[i][i] = 1;
        while (n)
        {
            if (n & 1) cheng();
            n >>= 1;
            fan();
        }
        swap(a, b);
    }
    
    int main()
    {
        scanf("%d%d%I64d", &n, &m, &yu);
        scanf("%s", s);
        make_next();
        f[0] = 1;
        for (int i = 0; i < m; ++i) //已经匹配 i 位 正在匹配第 i+1 位 
        {
            for (int j = '0'; j <= '9'; ++j) // 第 i+1 位是 j 
                if (j == s[i]) a[i+1][i] ++; // success
                else // fail  find the last can pipei
                {
                    int x = next[i];
                    while (x != -1 && s[x] != j)
                        x = next[x];
                    a[x+1][i] ++;
                }
        }
        mi(n);
        long long ans = 0;
        for (int i = 0; i < m; ++i)
        {
            long long zan = 0;
            for (int j = 0; j < m; ++j)
                zan = (zan + f[j] * a[i][j]) % yu;
            ans = (ans + zan) % yu;
        }
        printf("%I64d
    ", ans);
    }
  • 相关阅读:
    (三) 权限控制 --《springboot与shiro整合》
    (二) shiro集成 --《springboot与shiro整合》
    (一) springboot 项目搭建 --《springboot与shiro整合》
    第四章 编码/加密(学习笔记)
    第三章 授权(学习笔记)
    第二章 身份验证(学习笔记)
    获取小程序码java实现
    paypal退款 java实现
    并发下的数据处理和优化
    Casperjs初体验
  • 原文地址:https://www.cnblogs.com/handsomeJian/p/3983427.html
Copyright © 2011-2022 走看看