# 整除阈值 DP 与有序折半枚举 出题人解法:按参数规模结合整除阈值 DP 与有序折半枚举。Codex(GPT-6):两种算法的应用与推导,设计多询问规格、模概率实现、整数溢出处理及验证数据。整除分块和折半枚举均为已有算法技巧,不作为原创技巧署名。 首选程序为完整的单文件 [std.cpp](std.cpp)。另有以时间换空间的[四分流式解法](solution-alternative-streaming.zh.md)与[计算程序](alternative-streaming.cpp)。 ## 1. 概率与预处理 记 $D=10^6$ 、$P=998244353$ 、$a_i=p_iD^{-1}\bmod P$ .对概率使用模运算,对倍率使用精确整数运算,两者不能混用。 - $p_i=0$ 或 $m_i=1$ 的剑可以删除。 - $p_i=D$ 的剑必定贡献 $m_i$ 倍。删除它,并把每个询问的阈值改为 $\lceil K_j/m_i\rceil$ . - 阈值为 $1$ 的答案恒为 $1$ . 确定倍率的除法必须向上取整。例如必定提供 $3$ 倍时,原阈值 $5$ 要求其余剑至少达到 $2$ 倍。 以下推导中的 $n$ 指剩余剑数。所有剩余剑都满足 $01$ ,令 $T=K-1$ .设 $F_i(t)$ 为前 $i$ 把剑的倍率不超过整数 $t$ 的概率。按第 $i$ 把剑是否触发分类: $$ F_i(t)=(1-a_i)F_{i-1}(t)+a_iF_{i-1}(\lfloor t/m_i\rfloor) $$ 初始值为 $F_0(0)=0$ ,对 $t\ge1$ 有 $F_0(t)=1$ .答案为 $1-F_n(T)$ ,减法也在模 $P$ 意义下进行。 直接枚举所有阈值需要 $O(nK)$ 时间。但从 $T$ 出发,只有下面的阈值可能被访问: $$ \mathcal Q_T=\{0\}\cup\{\lfloor T/d\rfloor:1\le d\le T\} $$ 这是因为整数乘法满足: $$ \left\lfloor\frac{\lfloor T/d\rfloor}{m_i}\right\rfloor=\left\lfloor\frac{T}{dm_i}\right\rfloor $$ 当 $d\le\sqrt T$ 时,分母只有 $O(\sqrt T)$ 个;当 $d>\sqrt T$ 时,商小于 $\sqrt T$ .所以状态数只有 $O(\sqrt K)$ ,且对转移封闭。 ### 数组下标,不用哈希或二分 令 $s=\lfloor\sqrt T\rfloor$ 、$r=\lfloor T/(s+1)\rfloor$ .按升序存储 $0,1,\ldots,s$ ,再存储分母从 $r$ 递减至 $1$ 时的商。任一非零状态 $t$ 的下标为: $$ \operatorname{index}(t)= \begin{cases} t,&t\le s,\\ s+r-\lfloor T/t\rfloor+1,&t>s \end{cases} $$ 每次转移在常数时间内定位目标。处理一把剑时按阈值从大到小更新,使较小阈值仍保留上一层的值,因此只需一个概率数组。 归纳证明:初始数组表示空集合;每次转移将不触发和触发两类互斥事件的概率相加,状态集合又没有遗漏依赖,因此最终数组就是所定义的累计概率。 对全部询问分别计算,时间为 $O(n\sum_j\sqrt{K_j})$ ,额外状态空间为 $O(\sqrt{K_{\max}})$ ,其中 $K_{\max}=\max_jK_j$ . ## 3. 小剑数:有序折半枚举 令 $M=\max_j K_j$ .仍先计算不达标的概率,再用 $1$ 减去它。将剑分成尽量等大的两组,每组枚举触发集合及其倍率、概率权重。 ### 共同概率因子 先提出所有剑都不触发的共同因子: $$ C=\prod_i(1-a_i),\qquad w_i=\frac{a_i}{1-a_i}=\frac{p_i}{D-p_i}\pmod P $$ 触发集合 $S$ 的概率为 $C\prod_{i\in S}w_i$ .因此,建表时不触发的权重保持不变,触发的权重乘 $w_i$ ,两半合并后再乘 $C$ .预处理已删除必定触发的剑,分母均可逆。 ### 在线性总时间内建表 维护按倍率升序排列的列表。加入一把剑时,原列表和把原列表各倍率乘 $m_i$ 后的列表分别有序,用线性归并得到下一层。 只保留倍率小于 $M$ 的状态。因为所有倍率至少为 $1$ ,一旦某个部分乘积达到 $M$ ,继续乘其他倍率也不可能属于任何询问的不达标事件。每次归并前,只允许原倍率不超过 $\lfloor(M-1)/m_i\rfloor$ 的状态触发。这既安全剪枝,也保证实际执行的乘法结果小于 $M$ . 一组有 $h$ 把剑时,各层长度最多为 $1,2,4,\ldots,2^h$ ,所以归并总时间为 $O(2^h)$ .实现中每层仅二分一次以找到可触发的前缀,其总成本 $O(h^2)$ 也被 $O(2^h)$ 包含。不能对每个状态都二分,也不需要在枚举完以后进行比较排序。 归纳可知,每个保留的状态对应一个触发集合,且全部倍率小于 $M$ 的集合都被保留。相同倍率的不同集合可以分别保留,其权重都必须计入。 ### 前缀权重与双指针 记左右列表为 $(x_i,u_i)$ 和 $(y_j,v_j)$ .询问 $K$ 的不达标概率为: $$ C\sum_i u_i\sum_{j:x_iy_j