题解:P3193 [HNOI2008] GT 考试
题目
阿申准备报名参加 GT 考试,准考证号为
他的不吉利数字
阿申想知道不出现不吉利数字的号码有多少种,输出模
数据范围及约定
对于全部数据,
心路历程
看到题面就想暴力,每一步可以填写
个数字,然后每次 check()一下有没有匹配上;
此时int dfs(int cur, int match)就是记录“第几位、结尾匹配上了几个时的方案数”;考虑加记忆化,改成 DP;
发现对于一个cur, match一定的时候调用的是同一个函数;
所以就用表示前 位结尾匹配上 个的方案数; 意识到出现了错误。
因为我的dfs过程中,分为“继续匹配,匹配断掉”两种情况,而后者我match直接归零了;
然后发现这应该是一个的 fail[]跳转的过程;(我沿用自动机的命名方式)
看看在cur失配的时候匹配上的最长长度;这个时候用了
分钟左右,还是比较快速的,就进入到了优化环节;
首先是把记忆化搜索写成递推的版本,因为的数据是不能线性推的,只能加速递推;
于是改成了递推版本并且交了一发:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < m; ++j)
for (int num = 0; num <= 9; ++num) {
int ind = j;
while (ind && a[ind + 1] - '0' != num)
ind = fail[ind];
if (a[ind + 1] - '0' == num)
ind++;
if (ind < m) {
f[i][ind] = (f[i][ind] + f[i - 1][j]) % k;
// printf("transform:\tfrom%d\t->\t%d\n", j, ind);
}
}
// system("pause");
}此时拿下 40pts 的小数据分,然后我发现可以用滚动数组,因为只依赖上一行;
但是我有更大的发现:如果你尝试写下类似注释的内容,会发现对于每一个
,它的转移是一定的;
也就是说,状态转移的方式,对来说是个定值,只与 有关;
聪明的你一定想到可以写作一个矩阵了;就在此时我发现矩阵加速和普通递推的微妙关系:
只要把递推程序中f[][] = ...改成matrix[][] += ...就是矩阵的生成方式;
而原来滚动数组优化之后的一行,就是我们的答案向量;
(我喜欢用行向量,大家为什么都是列?)
而写成向量形式,本身就是反复以来,滚动贡献的一个过程;
不过矩阵加速又把递推过程本身分离开来,计算出每个初始值对最终答案的贡献是什么;然后的步骤非常简单,
写struct,写Pow,
把内层搬出去生成sol矩阵,用vec乘起来,
统计vec内的答案;
然后恭喜我自己掉了; 这很正常,我习惯了,
我回头检查fail[]的板子有没有打错,我自己再造了一个数据,发现fail正确;
我回头检查sol[][]矩阵有没有生成错误,我用刚刚的 40pts 程序对拍,发现正确;
问题只能出在vec答案向量上了,然而他的初始化是对的,vec[0][0] = 1;约 30mins 以后我开始生气了,我已经坐不住了,浑身发抖;
我走来走去,用手捶自己的腿;
我很疑惑,很生气,看了一眼我的struct Matrix,检查了矩阵乘法的下标,是正确的;然后惊喜的发现,我把
*打成+了!后来的故事,我把它改了之后一发 AC;
然后应该也有同学听到我在那边大喊大叫,在这里诚挚的道歉;
没办法,人把自己蠢到了就是会这样;
题解
大部分内容在“心路历程”都讲过了,但是写给那些认真做题追求效率不喜欢看唐人小故事的人看。
Step 1
- 考虑暴力尝试
填入,并且检查是否已经完全匹配了,如果是就 return 0;; - 发现之前匹配了一部分的地方不重要,只有结尾才能够扩展到整个;
- 所以检查匹配的方式就是记录一个变量
match表示已经匹配了多长了; - 最后一直存活到
cur = n + 1位置就说明可行解,return 1;;
Step 2
- 填入数字的时候会有失配现象,我们需要知道此时又匹配上了多少,而不是归零;
这个操作正是的精髓: fail[]跳转; - 发现对于同一个
cur, match调用同一个递归函数,对于此加记忆化; - 写作递推的形式,输出一下发生转移的位置,发现递推关系仅由
决定;
对于而言等效为一个固定的递推方式; - 结合数据量,望矩阵加速的方向靠,想到需要用
fail[]结合生成递推矩阵;
Step 3
- 你都已经把递推矩阵写出来了,已经无需多盐。
代码:
1 |
|
- Title: 题解:P3193 [HNOI2008] GT 考试
- Author: Firsry
- Created at : 2025-08-23 20:33:07
- Updated at : 2025-08-23 20:35:07
- Link: https://firsryfan.github.io/2025/08/23/题解:P3193-HNOI2008-GT-考试/
- License: This work is licensed under CC BY-NC-SA 4.0.