3. 剰余演算

競技プログラミングではしばしば剰余演算が必要となる。ここでその基本をまとめておく。

3.1. 剰余演算の基本的性質

次のような性質が成り立つ。

\begin{eqnarray*} (a\%p)\%p &=& a\%p\\ (ab)\%p &=& \{(a\%p)×(b\%p)\}\%p = \{(a\%p)×b\}\%p\\ (a+b)\%p &=& \{(a\%p)+(b\%p)\}\%p = \{(a\%p)+b\}\%p \end{eqnarray*}

%p%p = %pと捉えて%pをくくり出しているようにみれば覚えやすいかもしれない。

積、和が3つ以上の場合は注意を要する。

\[ (abc)\%p = \{(ab)\%p×(c\%p)\}\%p = \{(ab)\%p×c\}\%p = [\{(a\%p)×b\}\%p×c]\%p \]

aの剰余をとる \(\to\) bを掛けて更に剰余をとる \(\to\) cをかけて更に剰余をとる、の手順でok。4つ以上も同じ。

割り算についてはさらに注意が必要である。 \((a/b)\%p = (ab^{-1})\%p\) と書けるが、 \(b^{-1}\) は通常の逆元ではない。逆元は

\[(ax)\%p = 1\%p\]

を満たすxがaの逆元として定義される。 逆元はフェルマーの小定理を用いて計算することが出来る。

フェルマーの小定理より

\[a^{p-1}\%p = aa^{p-2}\%p= 1\%p\]

であり、これから

\[a^{-1}\%p = a^{p-2}\%p\]

となる。すなわち

\[(a/b)\%p = \{(a\%p)\times (b^{p-2})\%p\}\%p\]

と、積に帰着できる。

例えば \((143/13)\%7 = (143\times 13^5)\%7\) となるわけである。

  • \(2^N\%(10^9+7)\) を求める例
#include <iostream>
const int MOD = 1000000007;

int main()
{
	long long N; std::cin >> N;
	int ans = 1;
	for(int i=0; i<N; i++)
	{
		ans *= 2;
		ans %= MOD;
	}
	std::cout << ans << std::endl;
	return 0;
}