包除原理:重なりを引き戻す
Aに属する数とBに属する数を足すと、両方に属する数を二度数えます。共通部分を引いて補正します。
言語:Python / 計算量:2集合の例 O(log min(A,B))
考え方
- 2集合なら
- A∪B
- =
- A
- +
- B
- -
- A∩B
- 。
- 3集合なら各集合を足し、2集合の共通部分を引き、3集合の共通部分を足します。
- 倍数の共通部分は最小公倍数の倍数です。
具体例
1..10で2または3の倍数は、5個+3個-6の倍数1個=7個。
実装
from math import lcm
n=10;a=2;b=3
print(n//a+n//b-n//lcm(a,b))注意する条件
集合の数Kが増えると部分集合は2^K。重なりの計算コストも含めて見積もります。
確認問題
1..10で2または3の倍数は何個?
解答と理由
7
2,3,4,6,8,9,10です。
実装課題
N A B(1≤N,A,B≤10^18)。1..N の中でAまたはBで割り切れる数の個数。
入力:
10 2 3
出力:
7参考実装
from math import gcd
n,a,b=map(int,input().split());l=a//gcd(a,b)*b
print(n//a+n//b-n//l)