1 条题解

  • 0
    @ 2026-10-26 4:31:47

    思路与算法

    利用整数恒等式

    (nm)=(n−m+1)(n−m+2)⋯nm!.\binom nm=\frac{(n-m+1)(n-m+2)\cdots n}{m!}.

    本题 m≤104m\le10^4,即使 nn 很大,也只需计算分子和分母各 mm 项的模积。因为 pp 是素数且 m<pm<p,分母 m!m! 的每个因子都非零模 pp,所以分母可逆。费马小定理给出

    (m!)−1≡(m!)p−2(modp).(m!)^{-1}\equiv(m!)^{p-2}\pmod p.

    用二进制快速幂计算这个逆元,再与分子模积相乘。

    不能直接套需要 n<pn<p 的 n!/(m!(n−m)!)n!/(m!(n-m)!) 模逆元模板,因为本题允许 n≥pn\ge p。改用长度为 mm 的连乘后,只有分母需要可逆;若分子包含 pp 的倍数,结果自然为0。逐个处理 TT 组查询。

    正确性说明

    组合数乘积恒等式在整数上成立,即 m!(nm)=(n−m+1)⋯nm!\binom nm=(n-m+1)\cdots n。对 pp 取模后,因 m<pm<p 且 pp 素,m!m! 与 pp 互质,可以在同余式两侧乘其逆元,得到程序使用的公式。费马小定理保证非零分母的 p−2p-2 次幂就是逆元,包括 p=2p=2 时指数0的边界。二进制快速幂正确计算该幂,逐步取模保持乘积余数,因此每组输出均为组合数的余数;证明不要求 n<pn<p。

    复杂度

    单组初始化为 O(1)O(1),两组连乘为 O(m)O(m),模幂为 O(log⁡p)O(\log p),总时间 O(m+log⁡p)O(m+\log p);全部查询为 O(T+∑q(mq+log⁡pq))O(T+\sum_q(m_q+\log p_q))。额外空间 O(1)O(1),不预处理到 nn 或 pp,也不构造巨大的精确组合数。

    易错点

    1. 可逆条件是 m<pm<p 且 pp 素,不能把分子非零作为前提;分子为0时结果就是0。
    2. n≥pn\ge p 时不要给 n!n! 求逆。此题输入为 n,m,pn,m,p,不是某些Lucas题中的 n+m,m,pn+m,m,p。
    3. 模数2、m=nm=n、nn 跨越模数、最大 mm 均已覆盖。源称“正整数”,但模余数可以为0,不能输出 pp 代替0。
    4. 模内乘积小于 101810^{18},使用64位并在每次乘法后取模。
    5. 独立答案以任意精度整数的精确组合数再取模获得,并与小规模Pascal三角核对;训练数据非官方原版。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    ll power(ll a, ll b, ll mod) {
        ll answer = 1 % mod;
        while (b) {
            if (b & 1)
                answer = answer * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return answer;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        ll tests;
        cin >> tests;
        while (tests--) {
            ll n, m, p;
            cin >> n >> m >> p;
            ll numerator = 1, denominator = 1;
            for (ll i = 1; i <= m; i++) {
                numerator = numerator * ((n - m + i) % p) % p;
                denominator = denominator * i % p;
            }
            cout << numerator * power(denominator, p - 2, p) % p << '\n';
        }
    }
    
    • 1

    信息

    ID
    1663
    时间
    1000ms
    内存
    512MiB
    难度
    普及
    标签
    递交数
    1
    已通过
    1
    上传者