執行緒的五大狀態和方法(加程式碼解析)
排列組合
前言
說實話這是我小學時的噩夢
正文
為了更好的理解基礎概念,我們用一個題來展開:
給定一個集合\(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