组合数学 (习题): Mehta and the Typical Supermarket (HackerRank)

该博客探讨了一道组合数学问题,涉及利用容斥原理解决区间[L,R]内有多少数字能被N种硬币面值整除。通过举例说明,解释了如何计算这些数字,包括减去特定数目的最小公倍数来调整系数。" 100745576,6221609,JFinal代码生成器详解与使用技巧,"['Java', '数据库', 'JFinal框架']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mehta and the Typical Supermarket

题目大意

N N N 种硬币, 每种硬币无限个. 给定一个区间 [ L , R ] [L, R] [L,R], 问里面有多少个数字可以由 N N N 种硬币中的某一种组合出来. 也就是说问你区间内有多少个数可以被至少一枚硬币的面值整除

思路

典型的容斥原理, 比如有面值 2 和 3, 区间为 [ 1 , 10 ] [1, 10] [1,10], 那么其中可以被组合出来的数有 { 2 , 3 , 4 , 6 , 8 , 9 , 10 } \{2, 3, 4, 6, 8, 9, 10\} {2,3,4,6,8,9,10}, 很容易看出来, 如果一个数是这两个数的最小公倍数, 那么这个数应该被减掉 (系数为 − 1 -1 1), 同理, 如果一个数是其中三个数的最小公倍数, 那么其系数应为 + 1 +1 +1

代码

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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值