2014-01-18 132 views
2

你會如何計算一個組合,如(100,000選擇50,000)?計算大組合

我迄今嘗試過三種不同的方法,但由於顯而易見的原因每個人都有失敗:

1)動態編程 - 數組的大小隻是變得如此可笑的是賽格故障

unsigned long long int grid[p+1][q+1]; 

//Initialise x boundary conditions 
for (long int i = 0; i < q; ++i) { 
    grid[p][i] = 1; 
} 

//Initialise y boundary conditions 
for (long int i = 0; i < p; ++i) { 
    grid[i][q] = 1; 
} 


for (long int i = p - 1; i >= 0; --i) { 
    for (long int j = q - 1; j >= 0; --j) { 
    grid[i][j] = grid[i+1][j] + grid[i][j+1]; 
    } 
} 

2)蠻力 - 顯然計算甚至100!是不現實的

unsigned long long int factorial(long int n) 
{ 
    return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n; 
} 

3)乘式 - 我無法儲存他們只是大

const int gridSize = 100000; //say 100,000 
unsigned long long int paths = 1; 

for (int i = 0; i < gridSize; i++) { 
    paths *= (2 * gridSize) - i; 
    paths /= i + 1; 
} 

// code from (http://www.mathblog.dk/project-euler-15/) 

如果有幫助的情況下這樣做的目的是爲了解決「的值對於大型輸入,有多少路徑通過m×n網格「問題。也許我錯過了攻擊這個問題的辦法?

回答

1

這裏是遞歸公式,這可能有助於: -

NCK =(N-1)C(K-1)* N/K

使用一個遞歸調用爲(N-1)C( K-1)首先評估NCk的結果。

由於您的號碼會非常大,請使用以下選項之一。

  1. GMP
  2. 使用自己的實現,可存儲數字作爲數組二進制位的序列,並使用展位的乘法算法 和分工轉移&減。
2

「你將如何計算......」很大程度上取決於所需的精度。精確的結果只能用任意的精確數字(例如GMP)來計算,但很可能您並不需要確切的結果。

在這種情況下,我會使用斯蒂林近似作爲階乘(http://en.wikipedia.org/wiki/Stirling%27s_approximation)並用雙打來計算。擴展中的加數可以用來調整錯誤。維基百科頁面也會給你一個錯誤估計。