MOCK NOIP 20221018 日志

堪堪能接受的一场。前两题一个半小时左右做完,后两题实在没什么思路,打完所有可能的暴力之后跑路了。

他们告诉我题目名称可以从上到下连起来读。

一句话题解

A – (种)菜

可以发现,假若同时有 ai,ai+1\newcommand{\bigO}{\operatorname{O}}a_i,a_{i+1}ai+1,ai+2a_{i+1},a_{i+2} 都可合并,则取 ai,ai+2a_i, a_{i+2} 中任意一个合并之后,质因数集合总是变为原来的超集,另外一项仍可合并。

故而可以贪心合并所有合法的邻项,最终检查是否仅剩一项即可。注意到 [1,700][1,700] 仅含 125125 个质因数,故可以用 std::bitset 保存每一项的质因子集合。复杂度 O(128nω)O(\frac{128n}{\omega})赛时竟然还开了数组保存每个质因子的实际指数!

B – (养)狗

观察到标记为 L,R\texttt{L,R} 的狗只可能与同一行内 R,L\texttt{R,L} 的狗交友;U,D\texttt{U,D} 亦然。每一行、每一列之间的方案是两两独立的。分别对它们计数。

以同行内的 L,R\texttt{L,R} 为例。对于每一个 R\texttt{R},我们试图向左为其匹配一个 L\texttt{L},亦或不匹配。若左侧在匹配后剩余 kkL\texttt{L},则这条狗有 kk 种匹配方法。故而记 f(i,k),g(i,k)f(i,k),g(i,k) 表示在考虑前 ii 条狗(不分类别)后剩 kk 条标 L\texttt{L} 的狗的匹配方案数和所有方案的权值总和,转移分两类讨论即可。

时间复杂度 O(n3)\operatorname{O}(n^3)

C – 可

赛时想起 CF1734F – Zeros and Ones 含(两个数的和的)进位的二进制数位 DP 的一种方法:从高往低考虑每一位,同时记录“其和的二进制表示的末尾有多少个连续的 11”。

又想起可以从低位向高位填写,保存向更高位进位的信息;若有上限,则记录“当前是否有某一位大于上限的对应位且其更高位不小于上限对应位”。一个例子是 NOIP 2021 B – 数列,还有某到模拟赛题目,可惜我忘记了。不过这道题有 k20,lgx104)k\leq 20, \lg x\leq 10^4),还是十进制表示(这意味着要记录多达 180180 种进位情况),更不说需要枚举下一位填写的数字以计算 f(x)f(x),运行时间不可接受。

kx104kx\leq 10^420 pts\text{20 pts} 做法)

有一经典问题:带限制的非负/正整数多元方程解个数。求取方程 x1+x2++xn=m(i{1,,n},xiZ,xi[0,d]x_1+x_2+\cdots+x_n=m\quad(\forall i \in \{1,\cdots,n\},x_i\in \mathbb{Z},x_i\in[0, d]的解的个数。由容斥原理,它等于 g(n,m)=k=0n(1)k(nk)(mk(d+1)+n1n1)g(n,m)=\sum_{k=0}^{n}(-1)^k\binom{n}{k}\binom{m-k(d+1)+n-1}{n-1}

我们可在 O(lgx)\operatorname{O}(\lg x) 的时间内轻松计算 f(x)f(x),故枚举 i=1kxi=s\sum_{i=1}^{k}x_i=s,计算 f(s)g(s,k)f(s)g(s,k) 即可。

正解

我本以为会有更高明的办法作数位 DP,结果还是太单纯了。

正解竟然是上述解法的优化。考虑以下式子: s=0kxf(s)g(s,k)=i=0k(1)i(ki)s=0kxf(s)(si(x+1)+k1k1)=i=0k(1)i(ki)s=0kxf(s)[si(x+1)+k1]!(k1)![si(x+1)]!=i=0k(1)ik(ki)!i!s=0kxf(s)[si(x+1)+k1]k1(将阶乘转写为下降幂)=i=0k(1)ik(ki)!i!s=i(x+1)kxf(s)l=0k1[k1i](1)kl1[si(x+1)+k1]l(利用第一类斯特林数将下降幂化为普通幂)=i=0k(1)ik(ki)!i!l=0k1[k1i](1)kl1s=i(x+1)kxf(s)(s+αi)l,αi=i(x+1)+k1()=i=0k(1)ik(ki)!i!l=0k1[k1i](1)kl1s=i(x+1)kxf(s)p=0l(lp)spαilp=i=0k(1)ik(ki)!i!l=0k1[k1i](1)kl1p=0l(lp)αilps=i(x+1)kxf(s)sp=i=0k(1)ik(ki)!i!l=0k1[k1i](1)kl1p=0l(lp)αilp(s=0kxf(s)sps=0i(x+1)1f(s)sp)\begin{aligned} &\sum_{s=0}^{kx}f(s)g(s,k)\\ =&\sum_{i=0}^{k}(-1)^i\binom{k}{i}\sum_{s=0}^{kx}f(s)\binom{s-i(x+1)+k-1}{k-1}\\ =&\sum_{i=0}^{k}(-1)^i\binom{k}{i}\sum_{s=0}^{kx}f(s)\frac{[s-i(x+1)+k-1]!}{(k-1)![s-i(x+1)]!}\\ =&\sum_{i=0}^{k}\frac{(-1)^ik}{(k-i)!i!}\sum_{s=0}^{kx}f(s)[s-i(x+1)+k-1]^{\underline{k-1}}\quad\text{(将阶乘转写为下降幂)}\\ =&\sum_{i=0}^{k}\frac{(-1)^ik}{(k-i)!i!}\sum_{s={\color{red}i(x+1)}}^{kx}f(s)\sum_{l=0}^{k-1}\begin{bmatrix}k-1\\i\end{bmatrix}(-1)^{k-l-1}[s-i(x+1)+k-1]^l\quad\text{(}\href{https://oi-wiki.org//math/combinatorics/stirling/#%E4%B8%8A%E5%8D%87%E5%B9%82%E4%B8%8E%E6%99%AE%E9%80%9A%E5%B9%82%E7%9A%84%E7%9B%B8%E4%BA%92%E8%BD%AC%E5%8C%96}{\text{利用第一类斯特林数将下降幂化为普通幂}}\text{)}\\ =&\sum_{i=0}^{k}\frac{(-1)^ik}{(k-i)!i!}\sum_{l=0}^{k-1}\begin{bmatrix}k-1\\i\end{bmatrix}(-1)^{k-l-1}\sum_{s={\color{red}i(x+1)}}^{kx}f(s)(s+\alpha_i)^l,\quad \alpha_i=-i(x+1)+k-1\quad(*)\\ =&\sum_{i=0}^{k}\frac{(-1)^ik}{(k-i)!i!}\sum_{l=0}^{k-1}\begin{bmatrix}k-1\\i\end{bmatrix}(-1)^{k-l-1}\sum_{s={\color{red}i(x+1)}}^{kx}f(s)\sum_{p=0}^{l}\binom{l}{p}s^p\alpha_i^{l-p}\\ =&\sum_{i=0}^{k}\frac{(-1)^ik}{(k-i)!i!}\sum_{l=0}^{k-1}\begin{bmatrix}k-1\\i\end{bmatrix}(-1)^{k-l-1}\sum_{p=0}^{l}\binom{l}{p}\alpha_i^{l-p}\sum_{s={\color{red}i(x+1)}}^{kx}f(s)s^p\\ =&\sum_{i=0}^{k}\frac{(-1)^ik}{(k-i)!i!}\sum_{l=0}^{k-1}\begin{bmatrix}k-1\\i\end{bmatrix}(-1)^{k-l-1}\sum_{p=0}^{l}\binom{l}{p}\alpha_i^{l-p}\left(\boxed{\sum_{s=0}^{kx}f(s)s^p-\sum_{s=0}^{{\color{red}i(x+1)-1}}f(s)s^p}\right) \end{aligned}

若设 h(n,p)=s=0nf(s)sph(n,p)=\sum_{s=0}^{n}f(s)s^p,则框内部分等于 h(kx,p)h(i(x+1)1,p)h(kx,p)-h\left(i(x+1)-1,p\right)

h(n,p)h(n,p) 的计算可以通过数位 DP 实现。设下一位填写 ccf(x)f(10x+c),xp(10x+c)pf(x)\rightarrow f(10x+c), x^p\rightarrow (10x+c)^p 的贡献均可用二项式系数变成线性,同时转移 h(?,0k1)h(?,0\cdots k-1) 即可。至于 i(x+1)1i(x+1)-1 的真实数位情况,可以应用 2020 次高精度加法实现。

由于时限较紧,转移 hh 时需要统一计算 c=1,,9c=1,\cdots,9 以及 c=0c=0f(0)=1f(0)=1)的贡献而不能枚举,它是一个可以打表存储的小范围等幂求和式。

时间复杂度 O(lgxk3)\operatorname{O}(\lg xk^3)

正解 – 部分优化

发现 ()(*) 式中 αi\alpha_i 是一常数,于是我们暴力将其展开,能够得到一 k1k-1 次多项式。再应用类似过程计算即可。这玩意可比斯特林数方便多了。

D – 爱

上题解吧。

考虑 f(pc)=p114514c((p+1)1919810p114514)max(c2,0)f(p^c)=p^{114514c}\left(\frac{(p+1)^{1919810}}{p^{114514}}\right)^{\max(c-2,0)}

两部分是独⽴的,我们可以先求出第一个因数的乘积,再乘上第⼆个的乘积。

⾸先我们对于质因⼦ p1000p\leq 1000,每⼀个开⼀个数据结构维护和。可以使用分块,O(n)\operatorname{O}(\sqrt{n}) 更改 O(1)\operatorname{O}(1) 查询。

接下来剩下的每个数要么是质数,要么是 11。考虑没有修改操作,我们可以把所有质因子为 p>1000p>1000 的位置拎出来。记这些位置为 a1,a2,,aka_1,a_2,\cdots, a_k。然后加入 k2k-2 条线段 [ai,ai+2],i{1,,k}[a_i,a_{i+2}],\forall i\in \{1,\cdots,k\},权值为 (p+1)1919810p114514\frac{(p+1)^{1919810}}{p^{114514}},则第二部分的乘积便是 [l,r][l,r] 完整包含的所有线段的权值积。模拟可以发现,若从位置集合中删去/加入某个点,则发生变化的线段条数最多为 55。故这是一个带修改的二维偏序问题,可以用数据结构维护。

若采用树套树,需小心常数和空间问题,总时间复杂度为超大常数的 O(qlog2n)\bigO(q\log^2 n)。担心空间不够,我采用线段树套平衡树实现,可惜仅获得 80 pts\text{80 pts}

注意到在同一时刻,每一位置 ii 最多分别作为一条线段的左端点和另一条线段的右端点。同时我们查询的是区间积,10192608171019260817 是一质数,故乘法在 Z/p\mathbb{Z}/p 上存在逆运算,可以快速撤销更改。于是将整个序列分块,记块长为 SS,则我们查询 [l,r][l,r] 内线段权值积时,记块 j,j+1,,kj,j+1,\cdots,k 均完整包含在 [l,r][l,r] 内。使用树状数组维护左端点在块 ss,右端点在块 tst\leq s 内的所有线段的权值前缀积。则在 s[j,k]s\in[j,k] 块内查询 [s,k][s,k] 的数据,在散块内暴力即可。删除(乘权值逆元)和插入一条线段的复杂度为 O(lognS)\bigO(\log \frac{n}{S}),单次查询复杂度为 O(nSlognS+S)\bigO\left(\frac{n}{S}\log\frac{n}{S}+S\right),求导可以得到其最小值点在 S=nlognS=\sqrt{n\log n} 时取到(实际实现时可以更激进地减少块长)。这是目前除了 k-D Tree 跑得最快的解法

  • 2022年10月26日