N N N の上から i i i 桁目を N i N_i N i とし、N N N から上 i i i 桁を取り出した数を U i U_i U i とします。
ここで、N N N の K K K 進数での桁数を ∣ N ∣ |N| ∣ N ∣ としたとき、 U ∣ N ∣ = N U_{|N|}=N U ∣ N ∣ = N です。
求めたい値は、N m o d M = U ∣ N ∣ m o d M N\bmod M=U_{|N|}\bmod M N mod M = U ∣ N ∣ mod M です。
U i + 1 = K U i + N i + 1 U i + 1 m o d M = ( K U i + N i + 1 ) m o d M U i + 1 m o d M = ( K ( U i m o d M ) + N i + 1 ) m o d M \begin{aligned}
U_{i+1}&=KU_i+N_{i+1}\\
U_{i+1}\bmod M&=(KU_i+N_{i+1})\bmod M\\
U_{i+1}\bmod M&=(K(U_i\bmod M)+N_{i+1})\bmod M
\end{aligned}
U i + 1 U i + 1 mod M U i + 1 mod M = K U i + N i + 1 = ( K U i + N i + 1 ) mod M = ( K ( U i mod M ) + N i + 1 ) mod M
であることから、U i m o d M U_i\bmod M U i mod M のみを保持すればいいことが分かります。
上の漸化式を適切に実装することで O ( ∣ N ∣ ) = O ( log N ) O(|N|)=O(\log N) O ( ∣ N ∣ ) = O ( log N ) で解くことができました。
実装例(C++)
1
2
3
4
5
6
7
8
9
10
11
12 #include <bits/stdc++.h>
using namespace std;
int main ()
{
int K, M;
string S;
cin >> K >> M >> S;
long long ans = 0 ;
for (char c : S)
ans = (ans * K + (c - '0' )) % M;
cout << ans << endl;
}