競技プログラミング
逆元
0
どのような問題がありますか?

この記事は最終更新日から1年以上が経過しています。

投稿日

更新日

AtCoder ABC 186 E - Throne

ABC 186のEがさっぱりだったので復習。

問題

AtCoder ABC 186 E - Throne

  • N個の座席が円周状に並んでいて、1つは玉座
  • 初期位置は玉座から時計回りにS個ずれている
  • 1回の移動で、時計回りにK個ずれる
  • 何回移動すれば玉座に座れる?

以下、座席の位置を0~N-1、玉座を0とする。初期位置はSで、位置0に到達するための回数を求める問題となる。

解法の概略

  • 最大公約数(GCD)で行けるかどうか判定
  • 拡張ユークリッドの互除法(通称extgcd)を用いて逆元を求める
  • 逆元×移動したい個数が答え

最大公約数と移動可能性

NとKの最大公約数(GCD)をgとする。KとNは何倍してもgの倍数なので、ループして戻ってきてもgの倍数ごとの位置となる。すなわち、最小の移動単位がgであることを意味している。
特に、gが1より大きいときについて考えると、g未満のずれを解消することはできないということである。開始位置Sからg単位でしか移動できないので、位置を0にするためにはS % g = 0(Sをgで割った余りが0)でなければならない。
なので、まずNとKの最大公約数gを求め、S % g = 0でなければ不可とし、そうでない場合は、NとKとSをgで割っておく。そうすると以降、NとKは互いに素となるので、扱いやすくなる。

移動回数と周期性

NとKが互いに素のとき、同じ場所に戻ってくる回数について考えてみる。初期位置が0で、a回移動したあとの位置bは、Nごとに1周するのでNの余りとなり、b = (a × K) % Nと表すことができる。同じ場所に戻ってくるのはb = 0、すなわちa × KがNの倍数となるときである。それはNとKの最小公倍数(LCM)ということになるが、NとKは互いに素なので最小公倍数はN × Kである。つまり、N回移動するごとに同じ場所に戻ってくる。(周期Nごとに、N個の異なる位置を取る)

逆元と任意の場所への移動

問題を少し変形して、一つ隣の位置に行くことを考えてみる。もしa回の移動で一つ隣の位置に行けるならば、b個先の位置には、a × b回の移動で行けるはずである。
この問題では位置をNの余りで考えるので、Nを法とする合同式で扱っていることになる。それをmod Nと記述する。このような世界で便利な数に逆元がある。逆元はかけると1になる数であり、x × K ≡ 1 (mod N)となるxが逆元である。これはつまり、x回移動すると位置が1進むことを意味している。すなわち、逆元が求まれば移動回数が計算できそうである。

逆元の計算

ax + by = gcd(a, b)となるx, yは拡張ユークリッドの互除法(通称extgcd)で計算できる。ここではextgcdによりKx + Ny = 1となるx, yを計算する。mod Nで考えるとNyが消えてKx ≡ 1 (mod N)となる。xがmod NにおけるKの逆元であり、x回移動すると一つ隣の位置に行ける。
サンプルにあるN=998244353, S=897581057, K=595591169で逆元を計算すると-145577299となった。ただし求めたいのは正の移動回数なので、これを直接答えには使えない。ここでN回ごとに同じ位置に戻る周期性を利用すると、-145577299 + N = 852667054回の移動で隣に行けることがわかる。

移動回数の計算

初期位置Sから位置0に移動したいので、N - S個移動する。
隣に移動するのに(x + N) % N回必要なので、((x + N) % N) × (N - S)回移動すればよい。さらに、N回ごとに同じ位置に戻るので、答えは((x + N) × (N - S)) % Nとなる。また、N回周期なのでこれが最小値となる。
サンプルにあるN=998244353, S=897581057, K=595591169だと((-145577299 + 998244353) × (998244353 - 897581057)) % 998244353 = 85832276046249984 % 998244353 = 249561088となり出力例と一致した。
よくあるextgcdの実装では戻り値としてgcdを返すので、それを利用するなら以下のようになる。(C++)

long long x, y;
long long g = extgcd(k, n, x, y);
long long ans = (((x + n) * (n - s)) % n) / g;

余談

pが素数のときはフェルマーの小定理からap2 mod pでaの逆元が計算できるが、この問題ではNが合成数のこともあるので適用できない。

参考情報

新規登録して、もっと便利にQiitaを使ってみよう

  1. ユーザーやタグをフォローできます
  2. 便利な情報をストックできます
  3. 記事の編集提案をすることができます
ログインすると使える機能について
hotpepsi

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
新規登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
機械学習を発展させるための知識を発信しよう!
~
PHP強化月間~開発する上で知っておくべき知見を共有しよう~
~
0
どのような問題がありますか?
新規登録して、Qiitaをもっと便利に使ってみませんか

この機能を利用するにはログインする必要があります。ログインするとさらに下記の機能が使えます。

  1. ユーザーやタグのフォロー機能であなたにマッチした記事をお届け
  2. ストック機能で便利な情報を後から効率的に読み返せる
新規登録ログイン
ストックするカテゴリー