題目大意
有 種硬幣, 每種硬幣無限個. 給定一個區間 , 問裏面有多少個數字可以由這 種硬幣中的某一種組合出來. 也就是說問你區間內有多少個數可以被至少一枚硬幣的面值整除
思路
典型的容斥原理, 比如有面值 2 和 3, 區間爲 , 那麼其中可以被組合出來的數有 , 很容易看出來, 如果一個數是這兩個數的最小公倍數, 那麼這個數應該被減掉 (係數爲 ), 同理, 如果一個數是其中三個數的最小公倍數, 那麼其係數應爲
代碼
def gcd(a, b):
if b == 0:
return a
return gcd(b, a % b)
def lcm(a, b):
return result = a * b // gcd(a, b)
# 給定區間 L, R, 可以被 value 整除的數的個數
def nPlan(value, L, R):
right = R // value
left = L // value
if L % value == 0:
left -= 1
return right - left
def _solve(val, i, count, L, R):
if val > R:
return 0
if count == 0:
return nPlan(val, L, R)
result = 0
for j in range(i+1, N):
result += _solve(lcm(val, coins[j]), j, count-1, L, R)
return result
def solve(count, L, R):
result = 0
for i in range(N):
result += _solve(coins[i], i, count-1, L, R)
return result
_N = int(input())
N = 0
coins = []
for i in range(_N):
c = int(input())
# 如果某一個硬幣的面值被另一個整除, 那麼這個硬幣就沒用了
unique = True
for j in range(N):
if coins[j] % c == 0:
coins[j] = c
unique = False
break
if c % coins[j] == 0:
unique = False
break
if unique:
coins.append(c)
N += 1
for _ in range(int(input())):
L, R = map(int, input().split())
result = 0
for i in range(1, N+1):
result += (-1)**(i-1) * solve(i, L, R)
print(result)