1~nまでの逆元をO(n)で求める方法
参考にしたのは以下の@rng_58さんによるツイートです
導出が自明ではないのでメモ(少なくとも僕にとっては)
ideone.com/SOygoW これで 1 から N までの逆元が O(N) でもとまります
— rng_2さん (@rng_58) 2013年3月15日
@komaki__ i * (MOD/i) = MOD - MOD%i を変形すると出てきます
— rng_2さん (@rng_58) 2013年3月15日
逆元列挙のコード
以下のコードで1~nまでの逆元(mod m)をO(n)で求められます
// 1~nの逆元を求める(mod m) vector<ll> list_mod_inverse(ll n, ll m) { vector<ll> inv(n + 1); inv[1] = 1; for (int i = 2; i <= n; ++i) inv[i] = inv[m % i] * (m - m / i) % m; return inv; }
導出
説明では、mを法としています。また、式中の/除算は切り捨て除算です。
上記のコードではとして、逆元を求めています。この式を導出します。
mはと表すことができます。この式中のkは(m / i)に等しくなります。よって、となります。この式を変形をしていきます。
(※以下の式はです。)
より、
を掛ける
を掛ける
負の数を消す
以上です