けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder ARC 111 A - Simple Math 2 (緑色, 300 点)

上手に整理すれば、とてもシンプルな問題!

問題概要

正の整数  N, M が与えられる。

 10^{N} M で割った商  \displaystyle \lfloor \frac{10^{N}}{M} \rfloor M で割ったあまりを求めよ。

制約

  •  1 \le N \le 10^{18}
  •  1 \le M \le 10000

考えたこと

 M で割るような操作を 2 回しているので、 10^{N} M^{2} で割った余りを考えるとよいのだろうなというあたりをつける。

 10^{N} M^{2} で割ったときの商を  Q、あまりを  R として、

 10^{N} = M^{2}Q + R

とおく。さらに、 R M で割ったときの商を  Q'、あまりを  R' とすると

 10^{N} = M^{2}Q + MQ' + R

と表せることになる。さて、このとき、 10^{N} = M(MQ + Q') + R と表せることから、次のことが読み取れる。


  •  10^{N} M で割ったときの商は  MQ + Q' に一致する
  • さらに、 MQ + Q' M で割ったあまりは  Q' に一致する
  • したがって、求める値は  Q' である

よって、この問題は「 10^{N} M^{2} で割ったあまりを  M で割った商」を求めることで解ける。

計算量は  O(\log N) となる。

コード

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

long long modpow(long long a, long long n, long long mod) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

int main() {
    long long N, M;
    cin >> N >> M;
    cout << modpow(10LL, N, M * M) / M << endl;
}