【题解】Solution Set - NOIP2024集训Day32 数位 dp

【题解】Solution Set - NOIP2024集训Day32 数位 dp

https://www.becoder.com.cn/contest/5537

order:1,3,5,6,2,4


「SDOI2013」淘金

就是要算前 \(k\) 大的和。

考虑一个位置 \((i,j)\) 在变化完了之后的金子个数。(也即逆变换。

设:\(f^\prime(x)\) 表示在 \(1\sim N\) 范围内,数位积为 \(x\) 的个数。

所以这个个数就是 \(f^\prime(i)f^\prime(j)\)

考虑用数位 dp,根号分治转移,算这个 \(f^\prime(x)\),应该可以做到 \(O(12\sqrt{9^{12}})\)


16:30 passed...

(主要是很不确定上面这个东西的正确性,然后去参考了一下题解,发现似乎没有我这种做法。😅

其实这个题最核心的地方,就是要缩减 dp 的状态数,上面是根号分治,下面是其他两个主流做法:

  1. 利用每个元素范围都是 \(1\sim9\),所以最终成绩一定可以表示为:\(2^a3^b5^c7^d\)

    这样状态数就是 \(O(\log_2N\log_3N\log_5N\log_7N)\approx 244,411\) 的了。

  2. 在一个较大范围内,不同的 \(f(x)\) 的个数实际上是不多的。

    \(1\le x\le 10^{12}\),个数为 \(8282\)

    所以我们考虑把这 \(8282\) 个先跑出来,然后在这 \(8282\) 个之间转移就行了。

    (主打的就是一个神奇结论。


嘶,我傻了。我那个根号分治只适用于算小于等于 \(x\) 的。

而且状态是离散的,所以也没办法算用差分算出恰好等于的个数。

emmm,所以假了。


然后我们现在是要求乘积的前 \(k\) 大。

直接拉取出来是 \(9^{12}\) 的级别的,显然不行。

我们对于每一个 \(i\),肯定是从大到小去匹配,指针的移动是具有单调性的,拿一个大根堆动态维护就行了。



「CF55D」Beautiful numbers

一定有 \(1\le y\le 9\)

我们 \(2^9\) 去枚举 \(x\) 中非 \(0\) 数有哪些。这样总的模数也就确定了,并且这个模数不会超过 \(9\times8\times7\times5\approx2520\)

直接定义:\(f_{i,j}\)\(i\) 位,和对当前枚举的模数取模余数为 \(j\) 的个数。

然后就没了。

(eh? 6min 速切 *2500?而且还打了这么打一串文字?

posted @ 2024-09-19 15:54  CloudWings  阅读(7)  评论(0编辑  收藏  举报