递推打表求逆元

递推打表求乘法逆元

  • 目的:得到在(mod m)的意义下的[2, n)区间内每个数分别对应的逆元
  • 推导出递推表达式:
    • 任取一个同余式 a x ≡ c ( m o d m ) ax \equiv c(mod m) axc(modm)消去a与c,得到x关于m的式子即为递推表达式
    • 对于这个同余式,一定存在一个数y使得 a x − c = m y ax - c = my axc=my
    • 根据定义 c ∗ ( c 的 逆 元 ) ≡ 1 ( m o d m ) c * (c的逆元) \equiv 1(mod m) c(c)1(modm)
    • 我们把c的逆元放在inv数组里,所以 c ∗ i n v [ c ] ≡ 1 ( m o d m ) c * inv[c] \equiv 1(mod m) cinv[c]1(modm)
    • 将 c 替换为 a x − m y ax - my axmy ( a x − m y ) ∗ i n v [ c ] ≡ 1 ( m o d m ) (ax - my) * inv[c] \equiv 1(mod m) (axmy)inv[c]1(modm)
    • a x ∗ i n v [ c ] − m y ∗ i n v [ c ] ≡ 1 ( m o d m ) ax * inv[c] - my * inv[c] \equiv 1(mod m) axinv[c]myinv[c]1(modm)
      • 由于 m y % m = 0 my \% m = 0 my%m=0
      • 而原式等价于 ( a x ∗ i n v [ c ] ) % m − ( m y ∗ i n v [ c ] ) % m = 1 (ax * inv[c]) \% m - (my * inv[c]) \% m = 1 (axinv[c])%m(myinv[c])%m=1
      • 所以等价于 ( a x ∗ i n v [ c ] ) % m = 1 (ax * inv[c]) \% m = 1 (axinv[c])%m=1
    • 所以 a x ∗ i n v [ c ] ≡ 1 ( m o d m ) ax * inv[c] \equiv 1(mod m) axinv[c]1(modm)
      • a x − c = m y 中 , a = m y / x ; − c = m y % x ax - c = my 中,a = my / x;-c = my \% x axc=mya=my/xc=my%x
    • m y / x ∗ x ∗ i n v [ − m y % x ] ≡ 1 ( m o d m ) my / x * x * inv[-my \% x] \equiv 1(mod m) my/xxinv[my%x]1(modm)
    • 对于任意的y都满足此式,不妨取y = -1
    • − m / x ∗ i n v [ m % x ] ∗ x ≡ 1 ( m o d m ) -m / x * inv[m \% x] * x \equiv 1(mod m) m/xinv[m%x]x1(modm)
    • 在(mod m)的意义下, − m / x ∗ i n v [ m % x ] -m / x * inv[m \% x] m/xinv[m%x]是x的逆元
    • 为保证求得结果都为正数, ( m − m / x ) ∗ i n v [ m % x ] (m - m / x) * inv[m \% x] (mm/x)inv[m%x]
    • 所以在(mod m)的意义下, ( m − m / x ) ∗ i n v [ m % x ] (m - m / x) * inv[m \% x] (mm/x)inv[m%x]是x在区间[0, m)内的逆元
#include<cstdio>

int inv[100001];
int mod = 9973;

//在(mod 9973)的意义下,[2, 10000)分别对应的逆元
void Inv() {
    inv[1] = 1;

    for (int i = 2; i < 10000; i++)
        inv[i] = (mod - mod/i) * inv[mod % i] % mod;
}

int main()
{
    Inv();
    for (int i = 0; i < 20; i++)
        printf("%d ", inv[i]);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值