集合的排列与组合

《Introductory Combinatorics Fifth Edition》学习笔记:

排列和组合的区别在于放置和选择是否和顺序有关。

集合的排列:n元素集合的r排列A(n,r)=n*(n-1)*(n-2)……(n-r+1)=n!/(n-r)!

集合的组合:n元素集合的r组合C(n,r)=n!/(n-r)!/r! [组合不考虑顺序]

问题:将26个英文字母排序,要求a,e,i,o,u任意两个不能连续出现,这样的排序有多少个?

分析:26个英文字母的总排序数是A(26,26)=26!,5个元音字母至少两个连续出现的情况有C(5,2)*A(2,2)*25*A(24,24)=20*2*25!=40*25!,result=(26-40)*25!这显然不对。看来不适宜用减法原理(这样处理,集合2并不是所求集合的“补”,第二集合多计算了)。换一种思路:先把辅音字母排列好,A(21,21).接着用隔板法的思想,在22个空选出5个空再排列,于是得到,C(22,5)*A(5,5).result=21!*5!*22!/[(22-5)!*5!]=21!*22!/17!

循环排列:n个元素的排列不是线性的,而是呈现一个圆状,这样一个固定元素顺序的环在圆上只有一种结果(因为可以旋转,形状不变。可以理解为先固定一个起点元素,再对其他元素排列)。这样算来,3个元素的循环排列是A(3,3)/3=2,n元素的循环排列结果是A(n,n)/n=(n-1)!

n元素集合的循环r排列的数目是s=n!/(n-r)!/r。这是建立在每一部分都含有相同数目的r排列之上的。

问题:有n(3<=n<=20)个人围坐一个圆桌,其中有两人不愿意彼此挨着坐,共有多少圆桌位置设置方法?

分析:彼此挨着坐的人数是2所以这里可以用减法原理的思路来计算,s2=A(2,2)*(n-1-1)*(n-3)!.s1=(n-1)! 所以s=s1-s2=(n-1-2)*(n-2)!=(n-3)*(n-2)! 另外通过改变分析次序来足以安排座位也是可以的,先选一个起点元素,这个起点元素就设为那特殊的两个人之一,然后在他的右边和左边都安排其他非特殊的人,(n-2)*(n-3)*A(n-3,n-3)=(n-3)*(n-2)! [这里不用乘以C(2,1),因为设置起点元素是人为的]

编码:

#include <iostream>
#include<cstdio>
using namespace std;
typedef unsigned long long ull; //ull最多正常表示到22!
ull f[23];  
void getf(){
    f[0]=1;
    for(int i=1;i<=65;i++)f[i]=f[i-1]*i;
}
int main()
{
    getf();
    ull n;
    while(cin>>n){
        printf("%llu\n",(n-3)*f[n-2]);
    }
    return 0;
}

问题:用20个不同颜色的念珠做成项链,有多少种不同的项链成果?
分析:圆桌解题思路,19!,但是特殊的是项链还可以对称翻转所以s=19!/2.

n元素集合的子集数量:C(n,0)+C(n,1)+C(n,2)+……+C(n,n)=2^n。(因为C(n,t)就是(x+y)^n的项的系数,特别地,当x=1,y=1时(x+y)^n的结果也就等于C(n,0)+C(n,1)+C(n,2)+……+C(n,n)的和,即2^n )


在Java中,两个集合排列组合通常是指从两个集合中分别取出元素来形成一个新的组合。如果我们有两个集合A和B,那么一个简单的排列组合就是取出A中的一个元素和B中的一个元素,形成一个包含两个元素的组合。以下是一些排列组合的基本思路: 1. 遍历组合:可以通过两层循环来遍历两个集合,第一层循环遍历集合A的元素,第二层循环遍历集合B的元素,这样就能得到所有的组合。例如,对于集合A = {a1, a2}和集合B = {b1, b2},组合可以是(a1, b1), (a1, b2), (a2, b1), (a2, b2)。 2. 列表的笛卡尔积:可以使用嵌套循环或者使用库函数来得到两个集合的笛卡尔积。在Java中,可以使用Stream API来实现,代码示例如下: ```java import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class CartesianProduct { public static void main(String[] args) { List<String> setA = Arrays.asList("a1", "a2"); List<String> setB = Arrays.asList("b1", "b2"); List<String[]> cartesianProduct = new ArrayList<>(); for (String a : setA) { for (String b : setB) { cartesianProduct.add(new String[] {a, b}); } } // 使用Stream API List<String[]> cartesianProductWithStreams = Stream.of(setA, setB) .map(s -> s.stream().toArray(String[]::new)) .reduce((s1, s2) -> Stream.of(s1, s2) .flatMap(a -> Arrays.stream(a)) .collect(Collectors.toList()).toArray(new String[0])) .map(s -> new String[] {s}).orElse(new String[0]); // 打印结果 cartesianProduct.forEach(strings -> System.out.println(Arrays.toString(strings))); cartesianProductWithStreams.forEach(strings -> System.out.println(Arrays.toString(strings))); } } ``` 3. 自定义排列组合逻辑:根据具体需求,可以自定义排列组合的逻辑。比如,可能需要考虑元素的重复性、组合的特定顺序,或者基于某些条件的组合选择等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值