排列组合——附力扣周赛301P4题解

排列组合

排列

定义

从n个不同元素中取出m(m≤n)个元素,按照一定的顺序排成一列,叫做从n个元素中取出m个元素的一个排列(permutation),用符号 A(n,m)表示。。

计算方式

\[\mathrm{A}_{n}^{m}=n(n-1)(n-2) \cdots(n-m+1)=\frac{n !}{(n-m) !} \]

\[\mathrm{A}_{n}^{m}=\mathrm{C}_{n}^{m} \cdot \mathrm{A}_{m}^{m} \]

组合

定义

从n个不同的元素中,任取m(m≤n)个元素为一组,叫作从n个不同元素中取出m个元素的一个组合(combination),用符号 C(n,m) 表示。

计算方式

\[\mathrm{C}_{n}^{m}=\frac{\mathrm{A}_{n}^{m}}{\mathrm{~A}_{m}^{m}}=\frac{n(n-1)(n-2) \cdots(n-m+1)}{m !}=\frac{n !}{m !(n-m) !} \]

\[\mathrm{C}_{n}^{m}+\mathrm{C}_{n}^{m+1}=\mathrm{C}_{n+1}^{m+1} \]

增一法则

\[\mathrm{C}_{n}^{m}=\mathrm{C}_{n}^{n-m} \]

对偶法则

不同点

  • a是讲究顺序的,例如在A中1,2和2,1是不一样的;而c是不讲究顺序的,1,2和2,1在C计算时是相同的。

  • 从选出的几个元素中,任取两个,交换顺序,若结果不同,是排列,否则是组合。

  • 所谓排列,就是指从给定个数的元素中取出指定个数的元素进行排序;组合则是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。

隔板法

简介

在n个元素间插入(b-1)个板,即 把n个元素分成b组的方法。 在排列组合中,对于将不可分辨的球装入到可以分辨的盒子中而求装入方法数的问题,常用隔板法。
隔板法就是把m个相同单元分配成n组。这样m个单元中间有m-1个空格,分成n组需要n-1块隔板,所以就是c(m-1,n-1)种方法。

注:隔板法的单元必须是相同的。

示例

(常规)e.g.,将20个大小形状完全相同的小球放入3个不同的盒子,不允许有盒子为空,有多少种不同的方法?

  • 解析:球中间有19个空档,需要在这19个空档里加入2个隔板来分隔为3份,共有 C(20-1,3-1)=171 种方法。

(变体)e.g.,将20个大小形状完全相同的小球放入3个不同的盒子,允许有盒子为空,但球必须放完 ,有多少种不同的方法?

  • 分析:本题中的小球大小形状完全相同,故这些小球没有区别,问题等价于将小球分成三组,允许有若干组无元素,用隔板法。
  • 解析:将20个小球分成三组需要两块隔板,因为允许有盒子为空,不符合隔板法的原理,那就人为的再加上3个小球,保证每个盒子都至少分到一个小球,那就符合隔板法的要求了(分完后,再在每组中各去掉一个小球,即满足了题设的要求)。然后就变成待分小球总数为23个,球中间有22个空档,需要在这22个空档里加入2个隔板来分隔为3份,共有c(22,2)=231种不同的方法。

python相关库

math

math.factorial(n):求n的阶乘。
math.comb(n,k):等价于上述C(n,m)。

from math import factorial,comb
factorial(3)
# 6
comb(4,2)
# 6

scipy

scipy.special.perm(n,m):A(n,m)
scipy.special.comb(n,m):C(n,m)

from scipy.special import perm,comb
perm(3,2)
# 6.0
comb(3,2)
# 3.0

itertools

itertools.permutations([list],m):列举排列结果。
itertools.combinations([list],m):列举组合结果。

from itertools import combinations, permutations
list(permutations([i for i in range(1,4)],2))
#[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

list(combinations([1,2,3],2))
#[(1, 2), (1, 3), (2, 3)]

力扣周赛301P4题解

传送门:统计理想数组的数目
大概思路:将每个数进行质因数分解,求得每个质因子的个数。然后利用排列组合隔板法即可。

class Solution:
    def idealArrays(self, n: int, m: int) -> int:
        M = 10 ** 9 + 7
        ans = 1
        for i in range(2, m + 1):
            now = 1
            for j in range(2, int(i ** 0.5) + 1):
                if i % j == 0:
                    cnt = 0
                    while i % j == 0:
                        i //= j
                        cnt += 1
                    now = now * comb(n + cnt - 1, n - 1) % M
            if i != 1:
                now = now * n % M
            ans = (ans + now) % M
        return ans
posted @ 2022-07-10 22:27  岸南  阅读(36)  评论(0)    收藏  举报