例:{0,1,2} 取 3 個,共 10 種:
{0,0,0}, {0,0,1}, {0,0,2}, {0,1,1}, {0,1,2}, {0,2,2}, {1,1,1}, {1,1,2}, {1,2,2}, {2,2,2}
因此組合數為:
C(m + n - 1, n - 1) = C(m + n - 1, m)
元素: 0 1 2 取數: 2 0 1 → 球球 | 空 | 球 排列: ● ● | | ● 位置: 共 5 個位置,選 2 個放隔板
// 避免溢位:迭代相乘除以階乘
long long comb(int n, int k) {
if (k > n - k) k = n - k;
long long res = 1;
for (int i = 1; i <= k; i++) {
res = res * (n - k + i) / i;
}
return res;
}
// 可重複組合數
long long combinationWithRepetition(int n, int m) {
return comb(n + m - 1, m);
}
void gen(int n, int m, int start, List cur, List> ans) {
if (cur.size() == m) { ans.add(new ArrayList<>(cur)); return; }
for (int i = start; i < n; i++) {
cur.add(i);
gen(n, m, i, cur, ans); // i 不變 → 允許重複
cur.remove(cur.size() - 1);
}
}
隔板法將「可重複組合」轉化為經典「不重複組合」,是組合數學中最優雅的技巧之一。