1. 程式人生 > 實用技巧 >執行緒的五大狀態和方法(加程式碼解析)

執行緒的五大狀態和方法(加程式碼解析)

排列組合

前言

說實話這是我小學時的噩夢

正文

為了更好的理解基礎概念,我們用一個題來展開:

給定一個集合\(S\),內有\(n\)個元素,且\(1-n\)每個數恰好出現一次
如果不計順序,求出從集合\(S\)中選出\(m\;(m<=n)\)個元素的方案數

  • 不計順序就是說\((1,3,2)\)\((1,2,3)\)算兩種方案

我們想:既然不計順序,則第一個數有\(n\)種選擇方案,對於每種方案,第二個數有\(n-1\)種選擇方案,第三個數有\(n-2\)
以此類推,第\(m\)個數有\(n-m\)種選擇方案

所以:\(A^m_n=n\times(n-1)\times(n-2)\times\dots\times(n-m)=\dfrac{n!}{(n-m)!}\)

如果計順序呢?
也就是說\((1,3,2)\)\((1,2,3)\)算一種方案

\(\lambda(x)\)為含有\(x\)個的元素的集合的全排列個數

則我們發現,每個重複的集合都被恰好計算了\(\lambda(m)\)

所以:\(C^m_n=\dfrac{A^m_n}{\lambda(m)}=\dfrac{A^m_n}{m!}=\dfrac{n!}{m!(n-m)!}\)

插空與隔板

例如這麼兩個題

[1]已知三元一次方程\(x+y+z=13\),求這個方程的正整數解的個數
高斯消元黨請自覺往下面去

乍一看 這是什麼玩意 這完全沒有思路

但意思其實就是給你13個球,讓你用兩塊板子將其分隔成三部分
既然分隔,所以我們看的不是球的個數,而是空隙的個數

所以答案為:\(C^2_{12}=66\)

驗證程式:

#include<iostream>
#define F(a,b) for(int a=1;a<=b;a++)
int ans;
signed main(){
	F(i,13) F(o,13) F(p,13)
		if(i+o+p==13) ans+=1;
	std::cout<<ans;
}

out: 66

[2]已知三元一次方程\(x+y+z=13\),求這個方程的非負整數解的個數

非負說明了可能有零的出現

意思其實就是給你13個球,讓你分到3個箱子裡,每個箱子允許不放
就等價於每個箱子事先放進去1個,然後13個球讓你分到3個箱子裡,每個箱子裡至少有一個
就相當於16個球用倆板子分成三部分

所以答案為:\(C^2_{15}=105\)

驗證程式:

#include<iostream>
#define F(a,b) for(int a=0;a<=b;a++)
int ans;
signed main(){
	F(i,13) F(o,13) F(p,13)
		if(i+o+p==13) ans+=1;
	std::cout<<ans;
}

out: 105