Language agnostic 用于确定具有非无序选择的无序组合数的函数

Language agnostic 用于确定具有非无序选择的无序组合数的函数,language-agnostic,math,combinatorics,Language Agnostic,Math,Combinatorics,我试图确定一个函数,用于确定具有非唯一选择的无序组合的数量 鉴于: n = number of unique symbols to select from r = number of choices 例如。。。对于n=3,r=3,结果将是:(编辑:添加Dav指出的缺失值) 我知道排列(无序、唯一的选择)的公式,但我不知道允许重复如何增加集合。如果你有N个唯一的符号,并且想要选择长度R的组合,那么你基本上是将N-1分隔符放入R+1“插槽”在所选符号的累计总数之间 0 [C] 1 [C] 2 [C

我试图确定一个函数,用于确定具有非唯一选择的无序组合的数量

鉴于:

n = number of unique symbols to select from
r = number of choices
例如。。。对于n=3,r=3,结果将是:(编辑:添加Dav指出的缺失值)


我知道排列(无序、唯一的选择)的公式,但我不知道允许重复如何增加集合。

如果你有
N个
唯一的符号,并且想要选择长度
R
的组合,那么你基本上是将
N-1
分隔符放入
R+1
“插槽”在所选符号的累计总数之间

0 [C] 1 [C] 2 [C] 3
C是选择,数字是迄今为止所做选择的累计计数。实际上,当你“开始”选择某件事物时,你可以为每件可能的事物放置一个分隔符(假设你在放置任何分隔符之前先选择一件特定的事物,因此在
N-1
分隔符中为-1)

如果将所有分隔符都放置在点0处,则为所有选项选择了最后一项。如果你把所有的分隔符都放在第三点,那么你就为所有的选择选择了初始的东西。一般来说,如果将第i个分隔符放置在点k,那么对于该点和下一个分隔符的点之间的所有选择,都选择了i+1

由于我们试图在
R
插槽周围放置
N-1
非唯一项(分隔符是非唯一的,它们只是分隔符),因此我们只想排列
N-1
1和
R
0,这非常有效

(N+R-1)选择(N-1)
=
(N+R-1)/((N-1)!R!)

因此,最终的公式是
(N+R-1)/((N-1)!R!)
获取具有非唯一项选择的无序组合的数量


请注意,对于N=3,R=3,它的计算结果为10,这与您的结果相匹配。。。在上面添加注释中指出的缺失选项之后,C++中的

< P>给出了以下例程:

template <typename Iterator>
bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
   /* Credits: Mark Nelson http://marknelson.us */
   if ((first == last) || (first == k) || (last == k))
      return false;
   Iterator i1 = first;
   Iterator i2 = last;
   ++i1;
   if (last == i1)
      return false;
   i1 = last;
   --i1;
   i1 = k;
   --i2;
   while (first != i1)
   {
      if (*--i1 < *i2)
      {
         Iterator j = k;
         while (!(*i1 < *j)) ++j;
         std::iter_swap(i1,j);
         ++i1;
         ++j;
         i2 = k;
         std::rotate(i1,j,last);
         while (last != j)
         {
            ++j;
            ++i2;
         }
         std::rotate(k,i2,last);
         return true;
      }
   }
   std::rotate(first,k,last);
   return false;
}
模板
bool next_组合(常量迭代器优先,迭代器k,常量迭代器最后)
{
/*字幕:马克·纳尔逊http://marknelson.us */
if((first==last)| |(first==k)| |(last==k))
返回false;
迭代器i1=第一个;
迭代器i2=最后一个;
++i1;
如果(最后==i1)
返回false;
i1=最后一个;
--i1;
i1=k;
--i2;
while(第一个!=i1)
{
如果(*--i1<*i2)
{
迭代器j=k;
而(!(*i1<*j))++j;
标准:国际热核聚变实验堆交换(i1,j);
++i1;
++j;
i2=k;
标准:旋转(i1,j,最后);
while(last!=j)
{
++j;
++i2;
}
标准:旋转(k,i2,最后);
返回true;
}
}
标准::旋转(第一,k,最后);
返回false;
}
然后,您可以继续执行以下操作:

std::string s = "12345";
std::size_t r = 3;
do
{
   std::cout << std::string(s.begin(),s.begin() + r) << std::endl;
}
while(next_combination(s.begin(), s.begin() + r, s.end()));
std::string s=“12345”;
标准:尺寸=3;
做
{

std::cout不会
011
112
111
也会是选择吗?而且,排列是有序的。你在考虑无序的组合。啊,对了,我错过了这些;-)谢谢!你最后的公式中稍微有点输入错误,应该是:C(n,r)=((n+r)-1)!/((n-1)!r!)哎呀,你说得对。第二次忘了加-1。
std::string s = "12345";
std::size_t r = 3;
do
{
   std::cout << std::string(s.begin(),s.begin() + r) << std::endl;
}
while(next_combination(s.begin(), s.begin() + r, s.end()));