员工派遣(200)
- 员工工号连续,且从1开始;
- 从工号1-k中选择员工 派去 x国(需要nx人)、y国(需要ny人);
- 工号为x倍数的不去x国,工号为y倍数的不去y国;
- 找到最小的k,使得可以将编号1-k中的员工分配给x国、y国,且满足两国需求;
输入描述:
四个整数x,y,nx,ny;
2<x<y<30000,且x、y均为质数
1<nx,ny < 10^9
nx + ny <= 10^9
输出描述:
满足条件的最小的k
示例1
输入:
2 3 3 1
输出:
5
暴力求解:
- 从i=1开始,当nx、ny任意一个大于0(还需要人), 则继续循环
- 若 i 既不是x的倍数,也不是y的倍数,则可以去x国,也可以去y国,分配条件是看谁需要的人多,即nx、ny谁大,就优先分配给谁;
- 若i是x的倍数,则去y国(ny-=1);
- 若i是y的倍数,则去x国 (nx-=1);
- 若i同时是x 、y的倍数,则跳过
- i += 1 继续循环
- 最后输出 i-1 ,即为最小的k值;
# 用例
# 2 3 3 1
# 5
# 3 5 20 30
# 53
# 7 19 15 13
# 28
# 23 71 71 23
# 94
# 3 7 20 5
# 29
# 23 71 7100 2300
# 9405
# 23 71 710000 230000
# 940575
#
class Dispatch:
def solution(self, x, y, nx, ny):
i = 1
while nx > 0 or ny > 0:
if i % x == 0 and i % y == 0:
i += 1
continue
elif i % x == 0:
ny -= 1
elif i % y == 0:
nx -= 1
else: # 都可以去
if nx >= ny:
nx -= 1
else:
ny -= 1
i += 1
print(i-1)
if __name__ == '__main__':
dispatch = Dispatch()
while True:
try:
x, y, nx, ny = list(map(int, input().strip().split()))
dispatch.solution(x, y, nx, ny)
except KeyboardInterrupt: # EOFError
break
二分法:
# 输入
nums = [int(x) for x in input().split()]
x, y, count_x, count_y = nums
left = 1 # k 的最小值
# count_x + count_y <= 10^9
right = pow(10, 9) # k 最大值
# 求满足条件的 k的最小值
while True:
if left >= right:
break
else:
k = (left + right) >> 1 # 地板除 // 得到中间数 k
# 1->k中 能整除y的个数 k/y
# 能整除x的个数 k/x
# 既能整除x 又能整除y 的个数 k/x*y
# count_x - int(k/y) 得到一部分 既不能被x也不能被y整除数值
target = max(0, count_x - int(k / y) + int(k / (x * y))) \
+ max(0, count_y - int(k / x) + int(k / (x * y)))
# 左边是 既不能被x整除也不能被y整除 + 2*(既能被x整除也能被y整除)
if k - int(k / x) - int(k / y) + int(k / (x * y)) >= target:
right = k
else :
left = k + 1
print(left)