包除原理とは数え上げ組合せ論における基本的な結果のひとつです。

2つの有限集合 A と B の和集合に属する元の数を計算するには、まずそれぞれに属する元の数 |A| と |B| を足しあわせた後、それらの共通部分に属する元の数 |A ∩ B| を引き去ればよいです。両者の合計から重複を取り除くという考え方です。

|A ∪ B| = |A|+ |B| – |A ∩ B|
|A ∪ B ∪ C| = |A| + |B| + |C| – |A ∩ B| – |B ∩ C| – |C ∩ A| + |A ∩ B ∩ C|

1 から 100 までの自然数で 2 または 3 の倍数の個数を求めよ。

100 までならループを回して実際に割り切れる自然数の数を数える方法でも問題ないかもしれません。

では 100 までではなくもっと大きな数になったらどうでしょうか?

1 から 10^9 までの自然数で 2 または 3 の倍数の個数を求めよ。

これだと実際にループを回していては制限時間以内には終わりません。

2 の倍数の個数であれば 10^9 を 2 で割り端数を切り捨てれば求めることができます。3 の倍数の個数も同様に求めることができます。しかし単純に(2 の倍数の個数)+(3 の倍数の個数)が答えにはなりません。なかには 2 の倍数であり 3 の倍数でもある整数も存在し、単純にたすだけではこれらを2回カウントしてしまっています。(2 の倍数の個数)+(3 の倍数の個数)-(2 と 3 の公倍数の個数)が答えです。

では 2 または 3 または 5 の倍数の個数であればどうなるでしょうか?

この場合は(2 の倍数の個数)+(3 の倍数の個数)+(5 の倍数の個数)から(2 と 3 の公倍数の個数)と(3 と 5 の公倍数の個数)と(2 と 5 の公倍数の個数)を引いてしまうと、今度は(2 と 3 と 5 の公倍数の個数)を多く引きすぎてしまうのでこれをたさなければなりません。

もう少しこれを一般化して考えると(偶数個の自然数の公倍数の個数)を引き、(奇数個の自然数の公倍数の個数)を足せばよいということに気がつきます。

自然数 N と数列 A が入力される。
1 から N までの自然数で A_i で割り切れる数の個数を求めよ。

自然数 a と b の公倍数の個数であれば N を(a と b の最小公倍数)で割れば求めることができます。そこでまず最小公倍数を求める処理を定義します。最小公倍数は a と b の積を a と b の最大公倍数で割れば求めることができます。最大公約数は以下のようにユークリッドの互除法で求めることができます。

複数の自然数の最小公倍数は2つの自然数の最小公倍数を求める処理を繰り返すことで求めることができます。

数列のなかから1個以上の要素を取り出す組み合わせを作り、そのときの要素数が偶数か奇数かで解を加算するか減算するかを決めます。