edo1z blog

プログラミングなどに関するブログです

C++ 割ったあまり

参考

「1000000007 で割ったあまり」の求め方を総特集! 〜 逆元から離散対数まで 〜 - Qiita

分かりやすいmodの説明動画

www.youtube.com

www.youtube.com

基本

  • 掛け算、足し算、引き算は、計算途中で余りだす。
  • 引き算は、余りがマイナスになったらmodを足す。
  • 割り算は計算途中で余り出すのが通用しない。
  • 割り算は、逆元を出して、掛け算に変換する。

逆元

https://i.gyazo.com/d7b827885ebc4bfd89dadf462194c76b.png

  • 上記の式を満たすxのこと。
  • 例えば、mod 13の場合、1/7の逆元は2です。
  • 56 ÷ 7を13で割った余りを出すときに、56 x 2を考えればよくなります。

逆元の求め方

  • 1/a ≡ x (mod m) は、ax ≡ 1 (mod m) に変換できます。
  • 上記は、ax = my + 1 になるということです。
  • 変形すると、ax + my = 1 にできます。
  • aとmが互いに素であれば、整数x, yのペアが存在します。
  • xの出し方は、拡張ユークリッド互除法が使えます。

サンプルコード

#include <bits/stdc++.h>
using namespace std;
using LL = long long;

LL extgcd(LL a, LL b, LL &x, LL &y) {
  if (b == 0) {
    x = 1;
    y = 0;
    return a;
  }
  LL gcd = extgcd(b, a % b, x, y);
  LL oldX = x;
  x = y;
  y = oldX - a / b * y;
  return gcd;
}

LL modinv(LL a, LL m) {
  LL x, y;
  extgcd(a, m, x, y);
  return x;
}

int main() {
  LL a = 7, b = 13;
  LL x = modinv(a, b);
  cout << x << endl;
}

結果

2