为了更好的阅读体检,可以查看我的算法学习网
在线评测链接:P1228
题目内容
在一个神奇的糖果工厂中,有一种特殊的糖果叫做“奇妙糖果”。这种糖果非常受欢迎,因为它的口感和味道都非常好。
奇妙糖果的制作非常复杂,制造过程中要求每种原料的出现次数必须是 k k k 的倍数,其中 k k k 是一个给定的正整数。
在制造奇妙糖果的过程中,制造商们发现,他们可以通过选择不同的原料配方来制造出不同的口感和味道的糖果。他们想要快速计算出可以制造的所有糖果的数量,以便在生产计划中进行参考。
为了实现这个目标,他们需要编写一个程序来计算出可以制造的所有奇妙糖果的数量。
给定 n n n 个原料和正整数 k k k,以及每个原料的种类 a i a_i ai ,你的任务是计算出可以制造的所有的奇妙糖果的数量。
注意,这里的“奇妙糖果”是指使用 n n n 个原料的任意非空子序列制造出的糖果,其中每种原料的出现次数都是 k k k 的倍数。
子序列定义是数组中选择若干个元素按照原顺序组成的新数组。
输入描述
第一行输出为两个整数 n ( 1 ≤ n ≤ 50 ) n(1 \leq n \leq 50) n(1≤n≤50) 和 k ( 1 ≤ k ≤ 50 ) k(1 \leq k \leq 50) k(1≤k≤50) ,表示原料的个数。
第二行输出为 n n n 个整数,第 i i i 个整数为 a i a_i ai ( 1 ≤ a i ≤ 50 1\le a_i \le 50 1≤ai≤50 ),表示该原料的种类的编号。
输出描述
输出为一个整数,表示有多少使用 n n n 个原料的任意非空子序列制造出的糖果,其中每种原料的出现次数都是 k k k 的倍数。
样例1
输入
4 2
1 2 1 2
输出
3
说明
三种方案分别为:{1,1}, {2,2}, {1,2,1,2}
样例2
输入
5 2
1 2 1 2 1
输出
7
说明
七种方案分别为:{1,0,1,0,0}, {1,0,0,0,1}, {0,0,1,0,1}, {0,2,0,2,0}, {1,2,1,2,0}, {0,2,1,2,1}, {1,2,0,2,1} (0代表不选对应位置的原料)
思路:组合数学
不同数之间是独立的。所以根据乘法原理,我们可以分别求每个数的方案,最后乘起来。
对于某个数
x
x
x来说,假设出现次数是
c
n
t
x
cnt_x
cntx,方案就是
C
(
c
n
t
x
,
0
)
+
C
(
c
n
t
x
,
k
)
+
C
(
c
n
t
x
,
2
k
)
+
.
.
.
+
C
(
c
n
t
x
,
⌊
n
k
⌋
∗
k
)
C(cnt_x,0)+C(cnt_x,k)+C(cnt_x,2k)+...+C(cnt_x,\lfloor\frac{n}{k}\rfloor*k)
C(cntx,0)+C(cntx,k)+C(cntx,2k)+...+C(cntx,⌊kn⌋∗k) , 那么总答案就是
∏
x
∈
a
∑
i
=
0
⌊
n
k
⌋
C
(
c
n
t
x
,
i
)
\large \prod_{x \in a} \sum_{i=0}^{\lfloor\frac{n}{k}\rfloor} C(cnt_x , i)
x∈a∏i=0∑⌊kn⌋C(cntx,i)
类似的题目:
京东-2023.2.25-P1055 这题比本题难一些。但是思想是差不多的
代码
from collections import defaultdict
import math
n , k = list(map(int , input().split()))
a = list(map(int , input().split()))
# cnt 含义如上
cnt = defaultdict(int)
for x in a:
cnt[x] += 1
ans = 1
# 枚举 每个数
for x in cnt.keys():
t = 0
# 枚举次数
for y in range(0 , cnt[x] + 1 , k):
# 求组合数
t += math.comb(cnt[x] , y)
ans *= t
if ans == 0:
print(ans)
else:
print(ans - 1)