📌数学📌排列组合.txt
排列(Arrangement):从给定个数的元素中取出指定个数的元素进行排序。
组合(Combination): 从给定个数的元素中仅仅取出指定个数的元素,不考虑排序。

公式符号表示:
    A 排列数
    C 组合数
    n 元素的总个数
    m 选择的元素个数
    ! 阶乘

排列数公式
    A(n,m) = n(n-1)(n-2)...(n-m+1) = n! / (n-m) !
    规定 0! = 1
    全排列 A(n,n) = n!
eg:
    A(5,2) = 5*4 = 20
    A(5,5) = 5! = 120

组合数公式
    C(n,m) = A(n,m) / m! = n! / m!(n-m)!
    C(n,m) = C(n,n-m)
eg:
    C(5,2) = 5*4/2*1 = 10
    C(5,3) = 5*4*3/3*2*1 = 10

54张不同的扑克牌分4堆,3堆17张,1堆3张,排列组合数:
C(54,17)*C(37,17)*C(20,3) = 47153358767970 * 15905368710 * 1140 ≈ 8.5499038e+26
C(54,3)*C(51,17)*C(34,17) = 24804 * 14771069086725 * 2333606220 ≈ 8.5499038e+26
其量级远远小于md5的总量,倍数约为2.5125909e-12或3.9799556e+11,约4千亿分之一。

有重复元素的全排列计算,eg:2个a,3个b,4个c,9个元素全排列
C(9,2)*C(7,3)*C(4,4) = 1260
C(9,4)*C(5,3)*C(2,2) = 1260

34种麻将牌,每种4张,共136张,全排列数为
C(136,4)*C(132,4)...C(8,4)*C(4,4)
= (136*135*134*133/24) * (132*131*130*129/24)...(8*7*6*5/24)*(4*3*2*1/24)
= 136! / (24^34)
≈ 4.3269839e+185
其量级远远大于sha512总量,倍数约为3.227212e+31

========== ========== ========== ========== ==========

func Arrange(n, m int) int {
	res := 1
	for i := n - m + 1; i <= n; i++ {
		res *= i
	}
	return res
}

// FullArrange n最大值,32位12,64位20,超过溢出
func FullArrange(n int) int {
	res := 1
	for n > 1 {
		res *= n
		n--
	}
	return res
}

// Combine n安全最大值:int32(33),uint32(34),int64(61),uint64(62),超过该大小且m接近其一半时计算溢出。
func Combine(n, m int) int {
	res := 1
	start := n - m
	for i := 1; i <= m; i++ {
		res = res * (start + i) / i
	}
	return res
}