特殊的排列组合(详细分析+证明) 每日一遍,算法再见!

特殊的排列组合

1.重复排列

定义:1.一般的从n给物体中可重复的选取r个物体,把这r个物体排列成一行,称为n个不同物体的可重复排列,简称重复排列

一般的,在n个不同物体中,可重复的选取r个物体的排列数是 n r n^r nr,这个不难理解,r个位置,每一个位置都有n种选取方法。

2.重复组合

重复组合是不考虑排列位置的,举个例子,现在有两个物体a,b,选取4个物体组合有多少(允许重复选取)?

aaaa,aaab,aabb,abbb,bbbb一共5种。那么我们如何去算重复组合的方案树呢?这个问题相较于重复排列就要难一点了。

从n个不同物体中允许重复的选取r个物体的组合数是 C ( n + r − 1 , r ) . C(n+r-1,r). C(n+r1,r).

证明:我们假设n个不同物体被选择的次数分别是 x 1 , x 2 , x 3 , . . . . , x n , 其 中 x i > = 0 , 1 < = i < = n x_1,x_2,x_3,....,x_n,其中x_i>=0,1<=i<=n x1,x2,x3,....,xn,xi>=0,1<=i<=n,那么方案数即为
x 1 + x 2 + x 3 + . . . + x n = r x_1+x_2+x_3+...+x_n = r x1+x2+x3+...+xn=r的自然数解的个数,我们把 x 1 , x 2 , x 3 , . . . , x n 都 加 上 1 , 不 改 变 解 的 个 数 , 令 k i = x i + 1 x_1,x_2,x_3,...,x_n都加上1,不改变解的个数,令k_i=x_i+1 x1,x2,x3,...,xn1ki=xi+1
,那么问题就变成了求 k 1 + k 2 + k 3 + . . . + k n = r + n k_1+k_2+k_3+...+k_n=r+n k1+k2+k3+...+kn=r+n的正整数解的个数( k i > 0 k_i>0 ki>0),此时我们就可以用隔板法求解了,我们抽象的把r+n理解为有r+n给点,中间有r+n-1个空隙,然后我们需要用n-1个隔板插入到某些空隙中把r+n给点分成n部分,就想下面这样。
⚪ ⚪ 丨⚪…⚪丨 ⚪ ⚪
那么我们从r+n-1个空隙中选择n-1个空隙插入隔板,方案数是 C ( r + n − 1 , n − 1 ) = C ( r + n − 1 , r ) C(r+n-1,n-1)=C(r+n-1,r) C(r+n1,n1)=C(r+n1,r)
证毕!

3.不全相异的全排列

现在有3个红球,2个白球,把这5只球排成一行,问有多少种排法?其中白球与白球,红球与红球之间没有任何差别。
用a表示红球,b表示白球,得到下面10种排法
a a a b b , a a b a b , a a b b a , a b a a b , a b a b a , b a a a b , b a a b a , a b b a a , b a b a a , b b a a a aaabb,aabab,aabba,abaab,ababa,baaab,baaba,abbaa,babaa,bbaaa aaabb,aabab,aabba,abaab,ababa,baaab,baaba,abbaa,babaa,bbaaa

一般的,在不全相异的物体中,其中 n 1 n_1 n1个物体是相同的, n 2 n_2 n2个物体是相同的,…, n k n_k nk个物体时相同的。n个物体中不相同的物体一共有k种,即 n = n 1 + n 2 + . . . + n k n=n_1+n_2+...+n_k n=n1+n2+...+nk则这n个物体的全排列数 n ! / ( n 1 ! × n 2 ! × . . . . × n k ! ) n!/(n_1!×n_2!×....×n_k!) n!/(n1!×n2!×....×nk!)

4.圆周排列

上面的排列都是排成一排的形式,但如果是在一个圆上面,则称为圆排列,不同之处在于,圆排列是首位相连的,某些排列是等价的,例如abcd,dabc,bcda,cdab这四种排列就是等价的。

我们用Q(n,r)表示从n个不同物体种选择r个物体做圆排列,那么Q(n,r)=A(n,r)/r5,这个不难理解,因为圆上的排列,从每一个点出发绕一圈形成的排列方案都是等价,所以我们需要把所有的方案除以圆上点的个数也就是r。

例题:Lolihunte生日收到一条手链,由n课不同颜色的珠子串成的,有一天Lolihunte不小心把手链弄断了,珠子散了一地,他不记得珠子的排列顺序,现在问他能排出多少种链子?

分析:手链是一个圆周,由上面的圆周排列公式求解

代码:

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	int ans=1;
	for(int i=1;i<n;i++)
	{
		ans*=i;
	}
	cout<<ans<<'\n';
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值