首页 > 其他分享 >P3193 [HNOI2008] GT考试 解题报告

P3193 [HNOI2008] GT考试 解题报告

时间:2024-09-02 16:38:20浏览次数:9  
标签:GT P3193 int res 矩阵 times mar HNOI2008 Matrix

题目传送门

题目大意:

给定一个长度为 \(m\) 且只含 \(0\sim 9\) 的字符串 \(s\),求出所有长度为 \(n\) 的,只含 \(0\sim 9\) 且不含 \(s\) 字符串的数量,结果对 \(mod\) 取模。

数据范围:\(n\le 10^9,m\le 20,k\le 1000\)。

思路:

不难发现和 这道题 很像,只是 \(n\) 的数据范围被扩大到了 \(10^9\),\(m\) 的范围被缩小到了 \(20\)。

朴素 dp 思路在 状态机模型 dp 中写了,这里只讲优化。

朴素做法的时间复杂度为 \(O(nm)\),由于这道题的 \(n\) 很大,所以 TLE 无疑了。

观察一下状态转移方程:

\[f(i + 1, \delta(\pi (j), ch)) \leftarrow f(i, j) \]

对于每个 \(j\),它有 \(10\) 种状态,分别是字符 \(0\sim 9\),而若 \(j\) 和将要填的字符 \(ch\) 一定,那么 \(\delta(\pi (j), ch)\) 显然也一定,即转移到的地方也相同,而这种转移对于每一个 \(i\) 都要做一次,所以应该优化这个过程。

把状态转移方程展开,以 \(f(i + 1,0\sim m - 1)\) 这一层为例:

\[\left\{\begin{matrix} f(i + 1, 0) = a_{0, 0}\times f(i, 0) + a_{1, 0}\times f(i, 1) + \cdots + a_{m - 1, 0}\times f(i, m - 1) & & \\ f(i + 1, 1) = a_{0, 1}\times f(i, 0) + a_{1, 1}\times f(i, 1) + \cdots + a_{m - 1, 1}\times f(i, m - 1) & & \\ \vdots & & \\ f(i + 1, m - 1) = a_{0, m - 1}\times f(i, 0) + a_{1, m - 1}\times f(i, 1) + \cdots + a_{m - 1, m -1}\times f(i, m - 1) & & \end{matrix}\right. \]

这不就是矩阵乘法的形式吗?

根据上面的分析,我们构造的矩阵 \(A\) 与 \(i\) 无关,所以设 \(F(i) = \begin{bmatrix} f(i, 0) & f(i, 1) &\cdots & f(i, m - 1)\end{bmatrix}\),那么 \(F(i + 1) = F(i)\times A\),不难推出 \(F(n) = F(0)\times A^n\),然后就可以用矩阵快速幂算了。

现在的问题变成了如何构造矩阵 \(A\)。

根据状态转移方程,若 \(f(i, j)\rightarrow f(i + 1, p)\),那么说明要得到 \(f(i + 1, p)\) 要加上 \(f(i, j)\),即 \(A\) 矩阵中的第 \(j\) 行 \(p\) 列要加上 \(1\)。

为什么呢,看这张图就明白了:

其实图是我偷的(

那么矩阵 \(A\) 就构造好了,这道题也做完了。

流程:

先预处理 KMP 的 \(ne\) 数组,然后预处理出 \(A\) 矩阵,最后直接矩阵快速幂输出答案即可。

时间复杂度:\(O(m^3\cdot \log n)\)。

\(\texttt{Code:}\)

#include <cstring>
#include <iostream>

using namespace std;

const int N = 25;

int n, m, mod;
char s[N];
int ne[N];

struct Matrix {
    int mar[N][N];
    Matrix() {memset(mar, 0, sizeof mar);}
    void init() {
        memset(mar, 0, sizeof mar);
        for(int i = 0; i < m; i++)
            mar[i][i] = 1;
    }
    Matrix operator *(const Matrix &o) const {
        Matrix res;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < m; j++)
                for(int k = 0 ; k < m; k++)
                    res.mar[i][j] = (res.mar[i][j] + mar[i][k] * o.mar[k][j]) % mod;
        return res;
    }
}A;

int qpow(int k) {
    Matrix res;
    res.mar[0][0] = 1;
    while(k) {
        if(k & 1) res = res * A;
        A = A * A;
        k >>= 1;
    }
    int ans = 0;
    for(int i = 0; i < m; i++)
        ans = (ans + res.mar[0][i]) % mod;
    return ans;
}

int main() {
    scanf("%d%d%d%s", &n, &m, &mod, s + 1);
    for(int i = 2, j = 0; i <= m; i++) {
        while(j && s[j + 1] != s[i]) j = ne[j];
        if(s[j + 1] == s[i]) j++;
        ne[i] = j;
    }
    for(int j = 0; j < m; j++)
        for(int k = '0'; k <= '9'; k++) {
            int p = j;
            while(p && s[p + 1] != k) p = ne[p];
            if(s[p + 1] == k) p++;
            if(p < m) A.mar[j][p]++;
        }
    printf("%d\n", qpow(n));
    return 0;
}

标签:GT,P3193,int,res,矩阵,times,mar,HNOI2008,Matrix
From: https://www.cnblogs.com/Brilliant11001/p/18392942

相关文章

  • uniapp [安卓苹果App端] - 最新实现“热更新“在线版本升级详细教程,支持后端服务器、
    前言网上的教程乱七八糟且都有各种残缺不全的问题,文本提供优质教程及可靠方案。在uni-appApp端(安卓APP|苹果APP)开发中,详解实现WGT热更新整个前端和后端操作全流程,制作wgt热更新包、制作新版本更新通知提示框或页面源码,支持推送弹框提示用户更新软件或应用后台"静默(......
  • C++头文件<algorithm>中常用函数简介
     概述头文件algorithm(算法库)中主要提供了一些对容器操作的函数,如排序、搜索、复制、比较等,因此使用频率还是很高的,由于主要是操作容器,所以函数的语法也很类似:algorithm_name(container.begin(),container.end(),...);其中,container.begin()和container.end()分......
  • Gluon 编译 JavaFx -> android apk
    Gluon编译JavaFx->androidapk本文的内容属在linux服务器上搭建Gluon编译android-apk环境这一篇文章直接跟着官网操作一次性成功虚拟机版本centos8Architecture:x86-64开始安装相关前置工具gccversion6orhigherldversion2.26orhighersudoyumupd......
  • 正点原子Linux C应用编程:移植tslib并使其适配7寸LCD1024*600的GT911触摸驱动
    正点原子LinuxC应用编程:移植tslib并使其适配7寸LCD1024*600的GT911触摸驱动作者在学习【正点原子】I.MX6U嵌入式LinuxC应用编程指南V1.4时,发现移植tslib后,触摸事件触发不正常。使用的硬件版本:正点原子I.MX6UALPHAV2.4版本底板,LCD:正点原子7寸1024*600,型号ATK-MD0700R-102460......
  • Gluon 编译 JavaFx -> exe
    Gluon编译JavaFx->exe能力强的伙伴可以直接参考官方文档开发工具idea2023.3ideagluonplugingitapache-maven-3.8.4环境准备vs2022community版本(使用微软官方的安装器安装,社区版即可)jdk11or17+(可以使用idea进行下载安装)GraalVMCEGluon22.1.0.1-Fi......
  • C#中通用返回对象Result<T>(定义及使用)
     1.定义返回对象//Result对象是一种显式表示成功结果或失败的类型//方法可以返回这个类,而不是引发异常。如果操作失败,则Result对象将包含错误消息或代码,但不包含异常publicclassResult<T>{publicTValue{get;}publicstringEr......
  • 基于STM32F407ZGT6用BH1750在OLED显示屏上显示光照数据,根据光照强度控制小灯亮灭(路灯
    占空比:高电平占整个电平周期的持续时长,从而控制小灯的亮度,小灯亮度的控制需用定时器的输出比较功能。PWM部分可以参考这篇文章PWM——基于STM32F407ZGT6开发板-CSDN博客此外我们还需要了解IIC的工作原理1.pwm.c   #include"public.h"/*pwm控制led实现呼吸灯1.......
  • Node脚本打包uniapp热更新wgt文件
    通过脚本打包uniapp热更新wgt文件前言:uniapp只能通过hbuilder打包wgt文件目标:通过脚本命令打包wgt文件实现思路uniapp官方文档已经提供了wgt文件的的生成思路:目前使用npmrunbuild:app-plus会在/dist/build/app-plus下生成app打包资源。如需制作wgt包,将app-plus中的文......
  • 基恩士SR-X80系列扫码枪EIP通讯 ( 汇川AM401<->基恩士SR-X80 )
    第一步:扫码枪设置1,基恩士扫码枪IP地址设置 2,扫码枪EIP设置第二步:PLC设置及编程1,EDS文件导入  2,EIP配置 3,程序VARx触发读码:BOOL;接收数据长度:UINT;接收数据:ARRAY[0..127]OFBYTE;str接收数据:STRING;TRIG0:R_TR......
  • 网站提示411 Length Required:请求未包含Content-Length头怎么办
    当遇到“411LengthRequired”错误时,这意味着服务器要求客户端在请求中包含 Content-Length 头信息,以指示请求体的长度。这个错误通常出现在HTTP的POST、PUT和PATCH请求中,因为这些请求通常包含请求体。解决方案检查请求确认请求是否包含请求体。如果请求体为空,可......