我有这样的组合:
1,2,3,4 //索引0
1,2,3,5 //索引1
1,2,3,6 //索引2
依此类推,直到7,8,9,10
所以这将是组合学中的n = 10 k = 4
如何按指数计算组合
例如当我的索引== 1
时
myCmb = func(index)
返回1,2,3,5
这是一个例子,我需要这个最大数字,更多参数和没有(如果可能的话)许多循环
我找到这样的东西来获得位置: http://answers.yahoo.com/question/index?qid=20110320070039AA045ib
我现在要反过来......
我用C ++编程 感谢任何sugesstions或帮助
答案 0 :(得分:1)
好像你想要find the k-combination for a given number。
在example之后,这里应该有用:
#include <cstddef>
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
#include <boost/math/special_functions/binomial.hpp>
std::size_t Choose(double n, double k) {
using boost::math::binomial_coefficient;
if (n < k) return 0;
return static_cast<std::size_t>(binomial_coefficient<double>(n, k));
}
// Returns the largest n such that Choose(n, k) <= pos.
int CombinationElement(int k, int pos) {
int n = k;
int coeff = 1, prev_coeff = 0;
while (coeff <= pos) {
coeff = Choose(++n, k);
prev_coeff = coeff;
}
return n - 1;
}
// Returns an k-combination at position pos.
std::vector<int> Combination(int k, int pos) {
std::vector<int> combination;
for (; k > 0; --k) {
int n = CombinationElement(k, pos);
combination.push_back(n);
pos -= Choose(n, k);
}
return combination;
}
int main(int argc, char** argv) {
using std::cout;
using std::endl;
if (argc != 3) {
cout << "Usage: $ " << argv[0] << " K POS" << endl;
cout << "Prints the K-combination at position POS." << endl;
return 1;
}
int k = boost::lexical_cast<int>(argv[1]);
int pos = boost::lexical_cast<int>(argv[2]);
std::vector<int> combination = Combination(k, pos);
for (int i = 0; i < k; i++)
cout << combination[i] << " ";
cout << std::endl;
}
注意,为方便起见,代码依赖于Boost来计算二项式系数(boost::math::binomial_coefficient<T>
),并将字符串解析为整数(boost::lexical_cast
)。
答案 1 :(得分:1)
以下是Mathematica中的一个实现,来自包Combinatorica。语义是相当通用的,所以我认为它是有帮助的。如果您需要任何解释,请发表评论。
UnrankKSubset::usage = "UnrankKSubset[m, k, l] gives the mth k-subset of set l, listed in lexicographic order."
UnrankKSubset[m_Integer, 1, s_List] := {s[[m + 1]]}
UnrankKSubset[0, k_Integer, s_List] := Take[s, k]
UnrankKSubset[m_Integer, k_Integer, s_List] :=
Block[{i = 1, n = Length[s], x1, u, $RecursionLimit = Infinity},
u = Binomial[n, k];
While[Binomial[i, k] < u - m, i++];
x1 = n - (i - 1);
Prepend[UnrankKSubset[m - u + Binomial[i, k], k-1, Drop[s, x1]], s[[x1]]]
]
用法如下:
UnrankKSubset[1, 4, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}]
{1, 2, 3, 5}
如您所见,此功能可在集合上运行。
以下是我尝试解释上面的代码。
m
一个整数,从零开始的词汇顺序组合的“等级”。k
一个整数,每个组合中的元素数量s
一个List,用于组合组合的元素对于任何排名m
,以及任何列表s
,如果每个组合k
中的元素数量为1
,则:
将列表m + 1
中的s
元素返回到列表中。
(+ 1
是必需的,因为Mathematica从一个索引,而不是零。我相信C ++这将是s [m])
如果排名m
为0
,那么对于任何k
和任何s
:
返回k
s
元素
醇>
局部变量:(i
,n
,x1
,u
)
Binomial
是二项式系数:Binomial[7, 5]
= 21
执行:
i = 1
n = Length[s]
u = Binomial[n, k]
While[Binomial[i, k] < u - m, i++];
x1 = n - (i - 1);
然后返回:
Prepend[
UnrankKSubset[m - u + Binomial[i, k], k - 1, Drop[s, x1]],
s[[x1]]
]
也就是说,“prepend”列表x1
的{{1}}元素(记住Mathematica索引来自一个,所以我相信这将是C ++中的s
索引)返回的列表通过递归调用UnrankKSubset函数和参数:
x1 - 1
m - u + Binomial[i, k]
k - 1
Drop[s, x1]
是列表Drop[s, x1]
的其余部分,其中删除了第一个s
元素。
如果上述任何内容无法理解,或者您想要的是对算法的解释,而不是对代码的解释,请发表评论,我会再试一次。