1. 程式人生 > >c語言排列組合還可以這樣求

c語言排列組合還可以這樣求

本文主要講程式設計比賽中常用的排列組合。

首先,排列組合的公式是(其中P代表的就是A)

最普通的演算法就是按照公式求了,即分子算出來,分母算出來,然後相除,寫成程式碼為:

int c( int m,int n )
{
	int a = 1,b = 1, c = 1;
	for( int  i = 1 ; i <= m ; i++ )
		a = a*i;
	for( int i = 1 ; i <= n  ; i++  )
		b = b*i;
	for( int i = 1 ; i <= m-n ; i++  )
		c = c*i;
	return a/(b*c);
}

很顯然,這種方法不好,很容易溢位,只要資料範圍一大,就不能行了。

實際上,我們自己在紙上算排列組合的時候也並不是按照公式老老實實的算,其實可以化簡,即約分。

比如c(5,4)按照原來的方法=A(5,4)/!4,其實c(5,4)=c(5,1)= 5/1  = 1;

那麼就是c(m,n)= m*(m-1)*.......(m-n+1) / ! n  。

寫成程式碼為:

int c( int m,int n )
{
	int a = 1,b = 1;
	n = min(n,m-n);				//求簡單一點的  例如C(5,4) 可以求C(5,1)
	if( n == 0 )
		return 1;
	for( int i = m ; i >=m-n+1 ; i--  )
		a = a*i;
	for( int i = 1 ; i <= n ; i++ )
		b = b*i;
	return a/b;
}

這個方法相對於上一個好一點,但是還是有問題,資料太大會溢位,而且不能進行取模運算(反正我不知道)。

那麼,再介紹一種方法,遞推的思想,

其實排列組合還是挺有規律的,例如下面的

(1,1)  (1,2)  (1,3)  (1,4)  (1,5)  (1,6)

   1       2       3       4       5       6

         (2,2)  (2,3)  (2,4)  (2,5)  (2,6)

            1       3       6       10     15

                   (3,3)  (3,4)  (3,5)  (3,6)

                     1       4       10     20

                            (4,4)  (4,5)  (4,6)

                              1       5       15

                                      (5,5)  (5,6)

                                       1       6

                                               (6,6)

                                                1

因為具有對稱性,我只列了一半,高中書本里介紹過楊輝三角,其實很簡單,就是c(n,m)=c(n,m-1)+c(n-1,m-1),對應到上幅圖中就是:某一個 等於 這個的左邊的 加上 這個左邊的上邊的。即C(2,3) = C(2,2)+C(1,2)

那麼我們先把第一層算出來,然後遞推第二層,然後遞推。這種方法的優點是一次就把所有的求出來了,而且中間可以進行取模運算。

我們用一個二維陣列來儲存結果。

程式碼如下:

int a[1001][1001];					 
			//陣列的大小隨實際情況而定
			//陣列的型別最好為     long long
void c(  )
{
	memset(a,0,sizeof(a));
	for( int i = 1 ; i <= 1000 ; i++ )		//對第一層初始化 , 範圍視情況而定
		a[1][i] = i,a[0][i] = 1;
	for( int r = 2 ; r <= 1000 ; r++ )			//列舉行
		for( int c = r ; c <= 1000 ; c++ )	//列舉列
		{
			a[r][c] = a[r][c-1]+a[r-1][c-1];
			/*
			if( a[r][c] > mo )
				a[r][c] = a[r][c] % mo;			取模運算
															一般題目都會給一個mo,讓你取模
			*/
		}
}


本文只講了C(m,n),沒有講A(m,n),實在是能力有限,以後學到相關知識一定補充!