为了更好的阅读体检,可以查看我的算法学习网
本题在线评测链接:P1104
题目内容
塔子哥有两个机器,一个是他自己的电脑,另一个是他队友黑白胖球之一Cerq的电脑。
他现在有一个自己的任务,执行这个任务的消耗为一个正整数 c o s t cost cost ( 1 ≤ c o s t ≤ 2 × 1 0 5 1\le cost\le 2×10^5 1≤cost≤2×105 ),现在他把这个任务分成了 k k k ( 1 ≤ k ≤ c o s t 1\le k\le cost 1≤k≤cost )个子任务,每个子任务都是一个击杀对手或者完成目标的动作。他把这些子任务按照顺序分配给了两个机器,先让自己的电脑执行若干个子任务,然后再让Cerq的电脑执行剩下的子任务。这样做的目的是为了让两个机器的消耗恰好相等。
现在,请你帮忙编写一个函数,返回合法的切割方案数。由于答案可能过大你需要将答案对 1 0 9 + 7 10^9+7 109+7 取模。
样例 1 1 1
输入
8 3
输出
6
样例说明
-
(4) + (1+3)
-
(4) + (3+1)
-
(4) + (2+2)
-
(1+3) + (4)
-
(3+1) + (4)
-
(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(2n−1,i−1) 。因为可以看作 n 2 \frac{n}{2} 2n个 1 1 1摆成一排,有 n 2 − 1 \frac{n}{2}-1 2n−1个空隙,我们选择其中的 i − 1 i-1 i−1个空隙即可分成 i i i个部分了。
所以枚举
i
i
i,另一堆就是
k
−
i
k-i
k−i 。答案就是
∑
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=1∑k−1C(2n−1,i−1)∗C(2n−1,k−i−1)
答案比较大,需要取模+求逆元。类似的题目,我出过一个视频讲解的。大家可以看这里: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))