【备战秋招】每日一题:2023.03.21-阿里机试(第五题)-任务分配

文章讲述了如何将一个具有特定成本的任务拆分成子任务并公平地分配给两个机器执行,使得它们的消耗相等。提出了利用组合数学计算合法切割方案数的方法,并提供了Python代码实现。题目涉及到的主要概念包括任务成本、子任务数量、组合计算以及大数取模运算。
摘要由CSDN通过智能技术生成

为了更好的阅读体检,可以查看我的算法学习网
本题在线评测链接:P1104

题目内容

塔子哥有两个机器,一个是他自己的电脑,另一个是他队友黑白胖球之一Cerq的电脑。

他现在有一个自己的任务,执行这个任务的消耗为一个正整数 c o s t cost cost ( 1 ≤ c o s t ≤ 2 × 1 0 5 1\le cost\le 2×10^5 1cost2×105 ),现在他把这个任务分成了 k k k ( 1 ≤ k ≤ c o s t 1\le k\le cost 1kcost )个子任务,每个子任务都是一个击杀对手或者完成目标的动作。他把这些子任务按照顺序分配给了两个机器,先让自己的电脑执行若干个子任务,然后再让Cerq的电脑执行剩下的子任务。这样做的目的是为了让两个机器的消耗恰好相等。

现在,请你帮忙编写一个函数,返回合法的切割方案数。由于答案可能过大你需要将答案对 1 0 9 + 7 10^9+7 109+7 取模。

样例 1 1 1

输入

8 3

输出

6

样例说明

  1. (4) + (1+3)

  2. (4) + (3+1)

  3. (4) + (2+2)

  4. (1+3) + (4)

  5. (3+1) + (4)

  6. (2+2) + (4)

思路

​ 不难发现,就是将 n n n分成两堆,每堆 n 2 \frac{n}{2} 2n个数。对于一个堆,我们将其划分成 i i i个正整数相加的方案就是 C ( n 2 − 1 , i − 1 ) C(\frac{n}{2}- 1, i - 1) C(2n1,i1) 。因为可以看作 n 2 \frac{n}{2} 2n 1 1 1摆成一排,有 n 2 − 1 \frac{n}{2}-1 2n1个空隙,我们选择其中的 i − 1 i-1 i1个空隙即可分成 i i i个部分了。

​ 所以枚举 i i i,另一堆就是 k − i k-i ki 。答案就是
∑ i = 1 k − 1 C ( n 2 − 1 , i − 1 ) ∗ C ( n 2 − 1 , k − i − 1 ) \sum_{i=1}^{k-1}C(\frac{n}{2}- 1, i - 1) * C(\frac{n}{2}- 1, k - i - 1) i=1k1C(2n1,i1)C(2n1,ki1)

​ 答案比较大,需要取模+求逆元。类似的题目,我出过一个视频讲解的。大家可以看这里:https://www.bilibili.com/video/BV1GY4y1y7RA/?spm_id_from=333.999.0.0.

代码

python

def getMethods (cost , k):   
    mod = 1000000007
    fac = [1]
    for i in range(1 , 200006):
        fac.append(fac[-1] * i % mod)
    def ksm (a , b):
        ans = 1
        base = a 
        while b != 0:
            if b & 1:
                ans = ans * base % mod 
            base = base * base % mod 
            b >>= 1
        return ans 
    # 奇数不合法
    if cost % 2 != 0:
        return 0
    def comb (n , m):
		# 这里弄不明白的话先去搞清楚逆元取模!!
        if m > n:
            return 0
        x = fac[n]
        y = fac[m] * fac[n - m] % mod 
        return x * ksm(y , mod - 2) % mod
	# 公式如上
    n = cost // 2
    ans = 0
    for i in range (1 , k):
        ans = (ans + comb(n - 1 , i - 1) * comb(n - 1 , k - i - 1) % mod) % mod
    return ans  

cost , k = list(map(int , input().split()))
print (getMethods(cost , k))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

塔子哥学算法

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

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

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

打赏作者

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

抵扣说明:

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

余额充值