1 条题解

  • 0
    @ 2025-12-8 17:22:41

    题目理解

    我们需要计算 abmodp\frac{a}{b} \bmod p,其中 p=109+7p = 10^9+7aabb 可能是大整数(最多 50005000 位十进制数),并且 不保证 ab\frac{a}{b} 合法

    这里的「合法」是指:

    1. b≢0(modp)b \not\equiv 0 \pmod{p},即 bb 在模 pp 下有乘法逆元。
    2. 如果有解,解是唯一的(在模 pp 意义下)。

    「不合法」的情况就是 b0(modp)b \equiv 0 \pmod{p},此时分母在模 pp 下没有逆元,因此分数在模 pp 下无定义。


    核心思路

    题目提示已经给出:
    计算 abmodp\frac{a}{b} \bmod p 等价于计算 a×b1modpa \times b^{-1} \bmod p,其中 b1b^{-1}bbpp 的乘法逆元。

    乘法逆元

    对于质数 ppb≢0(modp)b \not\equiv 0 \pmod{p}b1modpb^{-1} \bmod p 存在且唯一,满足:

    b×b11(modp)b \times b^{-1} \equiv 1 \pmod{p}

    可以用 费马小定理 求:

    b1bp2(modp)b^{-1} \equiv b^{p-2} \pmod{p}

    因为 pp 是质数。

    负数处理

    题目说明:(A)modp=(Amodp)(-A) \bmod p = -(A \bmod p),这里是指结果的符号在模运算外处理。
    实际上在模 pp 运算中,我们通常将负数转为 [0,p1][0, p-1] 范围内的数。
    但在输出时,如果 a/ba/b 是负数,那么 a×b1modpa \times b^{-1} \bmod p[0,p1][0, p-1] 范围内会是正数,所以需要根据 a,ba,b 的符号来判断最终输出的正负号。

    更好的做法是:

    1. aabb 分别模 pp 得到 aa'bb'(在 [0,p1][0, p-1] 内)。
    2. 如果 b=0b' = 0,则无解。
    3. 否则计算 inv=bp2modpinv = b'^{p-2} \bmod p
    4. 计算 ans=a×invmodpans = a' \times inv \bmod p
    5. 如果原分数 ab\frac{a}{b} 是负数(即 a,ba,b 异号),且 ans0ans \neq 0,则输出 (pans)-(p - ans)
      不对,题目要求 (A)modp=(Amodp)(-A) \bmod p = -(A \bmod p),所以如果 ab\frac{a}{b} 是负数,那么结果应是 (a/bmodp)-(|a/b| \bmod p) 的形式。
      实际上更简单的做法是:计算 amodpa \bmod pbmodpb \bmod p 时保留符号信息(C/Java 取模规则),然后计算 (amodp)×invmodp(a \bmod p) \times inv \bmod p 得到的结果可能为负数,直接输出这个负数即可。

    实现步骤

    1. 读入 a,ba, b
      由于 a,ba,b 可能达到 10500010^{5000},需要用字符串读入。

    2. 判断 bmodpb \bmod p 是否为 0
      大数模 pp 可以通过逐位计算得到:
      res=0res = 0,对每一位数字 ddres=(res×10+d)modpres = (res \times 10 + d) \bmod p

    3. 如果 bmodp=0b \bmod p = 0
      输出 No Solution!

    4. 否则
      计算 amodpa \bmod pbmodpb \bmod p(注意负数取模规则:x % p 在 C/Java 中对负数得到 [p+1,0][-p+1, 0] 的值)。

      然后计算 b1=(bmodp)p2modpb^{-1} = (b \bmod p)^{p-2} \bmod p(快速幂)。

      计算 ans=(amodp)×b1modpans = (a \bmod p) \times b^{-1} \bmod p

      这里 amodpa \bmod p 可能为负数,所以乘完之后再模 pp 会得到负数(在 [p+1,p1][-p+1, p-1] 范围内),直接输出即可。


    样例验证

    样例 1

    a=1,b=2a=1, b=2
    bmodp=20b \bmod p = 2 \neq 0
    b1=2p2modp=500000004b^{-1} = 2^{p-2} \bmod p = 500000004
    ans=1×500000004modp=500000004ans = 1 \times 500000004 \bmod p = 500000004
    输出正确。

    样例 2

    a=1,b=2a=1, b=-2
    bmodp=2b \bmod p = -2(在 C/Java 中 2modp=2-2 \bmod p = -2
    b1=(2)p2modpb^{-1} = (-2)^{p-2} \bmod p,因为 pp 是质数,(2)p2(2p2)(modp)(-2)^{p-2} \equiv -(2^{p-2}) \pmod{p},所以 b1=(500000004)b^{-1} = -(500000004)
    ans=1×(500000004)modp=500000004ans = 1 \times (-500000004) \bmod p = -500000004
    输出正确。


    注意事项

    1. 大数取模时,负数要先判断符号,然后对绝对值取模,再恢复符号。
    2. 快速幂计算 bp2modpb^{p-2} \bmod p 时,bb 可能为负数,要处理好。
    3. 最终结果在 C/Java 取模规则下直接输出,不需要调整到 [0,p1][0, p-1]

    时间复杂度

    • 大数取模:O(len(a)+len(b))O(\text{len}(a) + \text{len}(b))
    • 快速幂:O(logp)O(\log p)p109p \approx 10^9,约 3030 次迭代。

    总复杂度对于 50005000 位大数完全可行。


    总结

    这道题本质是 大数取模 + 费马小定理求逆元,关键在于:

    1. 理解分数模质数的定义。
    2. 正确处理大数和负数取模。
    3. 判断无解条件 b0(modp)b \equiv 0 \pmod{p}

    只要思路清晰,实现起来并不复杂。

    • 1

    信息

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