1 条题解

  • 0
    @ 2025-12-9 18:36:46

    题意重述

    我们需要回答 TT 次询问,每次给出 n,mn, m,要求计算:

    $$S(n, m) = \sum_{i=0}^m \binom{n}{i} \bmod 998244353 $$

    其中 0mn0 \le m \le nnn 可达 9×1089\times 10^8TT 最多 88 次(因为测试点 i3i\ge 3T=i2T=i-2ii 最大 1010TT 最大 88)。


    第一步:基本思路

    如果 mm 很小,可以用 O(m)O(m) 直接计算组合数(预处理阶乘和逆元)。
    如果 mm 接近 nn,利用对称性 (ni)=(nni)\binom{n}{i} = \binom{n}{n-i},可以转化为求 S(n,nm1)S(n, n-m-1),然后用 2nS(n,nm1)2^n - S(n, n-m-1) 得到 S(n,m)S(n, m)

    但这里 nn 很大,不能预处理 O(n)O(n) 的阶乘,并且 mm[0,n][0, n] 均匀随机,所以不能假设 mm 很小或很大。


    第二步:利用组合数递推关系

    我们知道:

    $$\binom{n}{i} = \frac{n-i+1}{i} \cdot \binom{n}{i-1} $$

    因此,如果我们知道 (n0)=1\binom{n}{0}=1,可以 O(m)O(m) 逐个递推出 (n1),,(nm)\binom{n}{1}, \dots, \binom{n}{m},并累加。

    问题是 mm 可能接近 n/2n/2nn 很大时 O(m)O(m) 可能达到 O(n)109O(n) \approx 10^9,不可行。


    第三步:Lucas 定理不适用

    模数 998244353998244353 是质数,但 nn 可能大于模数,不过 nn 最大 9×1089\times 10^8,小于 998244353998244353(因为 998244353109998244353 \approx 10^9),所以 n<pn < p,Lucas 定理退化,就是普通组合数模 pp


    第四步:组合数求和公式的性质

    没有简单的闭式公式直接求 S(n,m)S(n,m),需要高效计算。

    一种思路:当 mm 接近 n/2n/2 时,可以用中心极限定理近似,但这是数学竞赛/ACM 题,必须精确模 pp


    第五步:分块打表 + 预处理

    因为 TT 很小(最多 88 次询问),我们可以对每个询问用 O(n)O(\sqrt{n})O(m)O(m) 算法,但 nn 很大,不能 O(n)O(n)

    关键观察nn 固定时,若 mm 均匀随机,期望 mn/2m \approx n/2,可能很大。
    TT 小,可以对每个询问用 O(min(m,nm))O(\min(m, n-m)) 的算法,最坏 O(n)O(n) 仍然太大。


    第六步:利用组合数递推 + 分块优化

    我们可以用分块计算组合数的方法:

    设块大小 B=nB = \sqrt{n} 或适当值,预处理某些 ii 处的组合数值,然后块间快速跳跃。

    具体来说:

    • 用公式 $\binom{n}{i+1} = \binom{n}{i} \cdot \frac{n-i}{i+1}$ 在块内递推。
    • 但块间跳跃需要快速计算 (nkB)\binom{n}{kB}

    计算 (nkB)\binom{n}{kB} 可以用:

    (nkB)=n!(kB)!(nkB)!modp\binom{n}{kB} = \frac{n!}{(kB)! (n-kB)!} \bmod p

    由于 n<pn < p,可以预处理阶乘和逆元到 nn?不行,nn 可达 9×1089\times 10^8,不能存整个阶乘数组。


    第七步:利用质数模下的快速阶乘计算

    对于质数 pp,有 O(plogp)O(\sqrt{p} \log p) 计算 n!modpn! \bmod p 的算法(基于多项式乘法和分段累乘)。
    这样我们可以在 O(plogp)O(\sqrt{p} \log p) 时间内算出一个 (ni)modp\binom{n}{i} \bmod p

    然后 S(n,m)S(n,m) 需要算 m+1m+1 个组合数,总复杂度 O(mplogp)O(m \sqrt{p} \log p)mm 大时还是慢。


    第八步:对称性优化

    由于 S(n,m)+S(n,nm1)=2nS(n,m) + S(n, n-m-1) = 2^n(模 pp),我们可以选择 mmnm1n-m-1 中较小的那个来计算部分和,然后用 2n2^n 减去得到原答案。

    因此我们可以保证只需要计算至多 n/2n/2 个组合数的和。

    即令 m=min(m,nm1)m' = \min(m, n-m-1),计算 S(n,m)S(n, m'),如果 m=mm' = m,则答案就是它;否则答案是 2nS(n,m)2^n - S(n, m')


    第九步:O(m)O(m) 递推 + 快速幂求逆元

    在模 pp 下,我们可以 O(m)O(m) 递推组合数:

    $$\binom{n}{i} = \binom{n}{i-1} \cdot \frac{n-i+1}{i} \pmod{p} $$

    除法用 ii 的逆元(预处理 11mm 的逆元,O(m)O(m))。

    由于 mn/2m \le n/2nn 可达 9×1089\times 10^8,最坏 m4.5×108m \approx 4.5\times 10^8O(m)O(m) 仍太大。


    第十步:注意到 TT 很小,但 mm 随机均匀

    题目说 mm[0,n][0,n] 均匀随机,那么 mm 的期望是 n/2n/2,可能很大,O(m)O(m) 不可行。

    因此需要更快的算法。


    第十一步:可能的 O(nlogn)O(\sqrt{n} \log n) 算法

    已知有算法可以在 O(nlogn)O(\sqrt{n} \log n) 时间内计算单个 (ni)modp\binom{n}{i} \bmod p(利用多项式乘法计算 k=1n(x+k)\prod_{k=1}^{\sqrt{n}}(x+k) 等技巧)。
    mm 个组合数求和,总复杂度 O(mnlogn)O(m \sqrt{n} \log n)mm 大时仍大。


    第十二步:分治 + 多项式乘法优化

    考虑生成函数:

    (1+x)n=i=0n(ni)xi(1+x)^n = \sum_{i=0}^n \binom{n}{i} x^i

    那么 S(n,m)S(n,m) 就是 (1+x)n(1+x)^n 的前 m+1m+1 项系数和。

    我们可以用多项式截断技术:
    计算 (1+x)nmod(xm+1)(1+x)^n \bmod (x^{m+1}),然后求系数和。
    多项式幂可以用快速幂在 O(mlognlogm)O(m \log n \log m) 时间计算。

    这里 mm 可能很大,但 logn\log n3030mm 大时 mlognlogmm \log n \log m 仍大。


    第十三步:实际可行算法(本题范围)

    由于 TT 很小,且 n9×108<pn \le 9\times 10^8 < p,可以这样做:

    对每个询问:

    1. m=min(m,nm1)m' = \min(m, n-m-1)
    2. m106m' \le 10^6,直接用 O(m)O(m') 递推求组合数并累加。
    3. 否则,用分块法:设块大小 B=105B=10^5,先计算 (n0),(nB),(n2B),\binom{n}{0}, \binom{n}{B}, \binom{n}{2B}, \dotsO(nlogn)O(\sqrt{n} \log n) 的阶乘算法,然后在块内递推。

    mm' 可能仍很大(接近 n/2n/2),不能直接 O(m)O(m')


    第十四步:本题标准解法(莫队式递推)

    有一种技巧:相邻 S(n,m)S(n,m) 有递推关系:

    S(n,m)=S(n,m1)+(nm)S(n,m) = S(n,m-1) + \binom{n}{m}

    并且

    S(n+1,m)=2S(n,m)(nm)S(n+1,m) = 2S(n,m) - \binom{n}{m}

    利用这个可以像莫队一样在 n,mn,m 变化时 O(1)O(1) 移动。

    但我们询问的 (n,m)(n,m) 是独立的,不连续,不能用莫队。


    第十五步:最终策略

    由于 TT 很小,我们可以对每个询问用 O(nlogn)O(\sqrt{n} \log n) 的算法计算 (ni)\binom{n}{i},然后 O(m)O(m) 累加,最坏 O(n)O(n) 不可接受,但题目数据是均匀随机 mm,且 TT 小,可能期望可以过。

    但更可靠的做法是:
    用分段打表,预处理一些关键点的阶乘值,然后用快速公式计算组合数。


    第十六步:总结

    本题是nn 组合数前缀和模质数问题,由于 TT 小,可以对每个询问用 O(min(m,nm)poly(logn))O(\min(m, n-m) \cdot \text{poly}(\log n)) 的算法,通过对称性减少计算量,并利用质数模下快速阶乘算法。

    核心算法

    1. 对称性减少 mm 至多 n/2n/2
    2. 用快速阶乘算法 O(plogp)O(\sqrt{p} \log p) 计算单个组合数。
    3. 递推求其他组合数并累加。

    复杂度:O(Tmplogp)O(T \cdot m \cdot \sqrt{p} \log p),最坏可能 10810^8 量级,但实际 TT 小且 mm 随机,可能可过。


    • 1

    信息

    ID
    5946
    时间
    4000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者