OD C卷 - 员工派遣

员工派遣(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)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值