aabbcc本质不同的排列数

本文探讨了由特定多重元素组成的排列问题,介绍了如何通过枚举算法找出所有可能的排列方式,并进一步研究如何识别这些排列中本质不同的类型。文中详细解释了如何判断一个排列是否为基本解,并给出了一种实现这一过程的程序设计方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
aabbcc本质不同的排列数
Stainhaus在其名著《一百个数学问题》中给出了如下问题:
“由aabbcc这组字母可以得出90种不同的排列,其中有些如aabcbc、aacbcb、bcbcaa及acacbb之间 并无本质差别,因为c、b互换,则可由第一个排列得出第2个排列,若逆向看第2个排列,可以发现它与第三个排列等价;而在第3个排列中,若将a、b互换,则生成第4个排列,我们将这种无本质差别的排列看成是相同类型的排列,而排列aabcbc和abcabc这两个排列无论用字母替换法还是逆向阅读法,甚至交替使用,也不能将前一种排列变为后一种,所以我们将这样的排列称为不同类型的排列。试问:aabbcc这6个字母共能组成多少种本质不同的排列类型。”
~~~~~~~~~~~~~~
多重元素集合的排列生成法
多重元素集合是指集合中一个元素可以重复出现多次的集合。例如多重元素集合{1,2,2,3,3,3}中元素1出现1次,2出现2次,3出现3次,而多重元素集合{1,1,2,2,3,3}中元素1、2、3均出现2次。多重元素集合的排列是指所有集合元素所构成的一个排列,一个元素在集合中出现几次,它在排列中同样要出现几次,例如,多重元素集合{1,1,2,2}共有6个不同的排列,它们分别是:
1122
1212
1221
2112
2121
2211
若一个集合中含k1个a1,k2个a2,…,kn个an,则该多重集合的不同排列数为:
(k1+k2+…+kn)!/k1!k2!...kn!
下面我们考虑多重元素集合的排列枚举算法。
我们将元素为表的表称为二重表,多重元素的集合可以表示成二重表的形式。例如,多重元素集合{1,2,2,3,3,3}表示成二重表[[1],[2,2],[3,3,3]]的形式。
domains
 ilist=integer*
 ilists=ilist*
 
predicates
 nondeterm dup_perm(ilists, ilist)
 nondeterm dup_perm_3(ilists, ilist, ilist)
 nondeterm merge(ilist, ilist, ilist)
 
clauses
 dup_perm([], []).
 dup_perm([L|Ls], P):-dup_perm_3(Ls, L, P).
 
 dup_perm_3([], P, P).
 dup_perm_3([L|Ls], P0, P):-
      merge(L, P0, P1),
      dup_perm_3(Ls, P1, P).
     
 merge([], L, L):-!.
 merge(L, [], L):-!.
 merge([X|L1], L2, [X|L]):-merge(L1, L2, L).
 merge(L1, [X|L2], [X|L]):-merge(L1, L2, L).
 
goal
 dup_perm([[1,1],[2,2],[3,3]], P),
 write(P), nl,
 fail.
上述目标生成的全部解为:

[3,3,2,2,1,1]
[3,2,3,2,1,1]
[3,2,2,3,1,1]
[3,2,2,1,3,1]
[3,2,2,1,1,3]
[2,3,3,2,1,1]
[2,3,2,3,1,1]
[2,3,2,1,3,1]
[2,3,2,1,1,3]
[2,2,3,3,1,1]
[2,2,3,1,3,1]
[2,2,3,1,1,3]
[2,2,1,3,3,1]
[2,2,1,3,1,3]
[2,2,1,1,3,3]
[3,3,2,1,2,1]
[3,2,3,1,2,1]
[3,2,1,3,2,1]
[3,2,1,2,3,1]
[3,2,1,2,1,3]
[2,3,3,1,2,1]
[2,3,1,3,2,1]
[2,3,1,2,3,1]
[2,3,1,2,1,3]
[2,1,3,3,2,1]
[2,1,3,2,3,1]
[2,1,3,2,1,3]
[2,1,2,3,3,1]
[2,1,2,3,1,3]
[2,1,2,1,3,3]
[3,3,2,1,1,2]
[3,2,3,1,1,2]
[3,2,1,3,1,2]
[3,2,1,1,3,2]
[3,2,1,1,2,3]
[2,3,3,1,1,2]
[2,3,1,3,1,2]
[2,3,1,1,3,2]
[2,3,1,1,2,3]
[2,1,3,3,1,2]
[2,1,3,1,3,2]
[2,1,3,1,2,3]
[2,1,1,3,3,2]
[2,1,1,3,2,3]
[2,1,1,2,3,3]
[3,3,1,2,2,1]
[3,1,3,2,2,1]
[3,1,2,3,2,1]
[3,1,2,2,3,1]
[3,1,2,2,1,3]
[1,3,3,2,2,1]
[1,3,2,3,2,1]
[1,3,2,2,3,1]
[1,3,2,2,1,3]
[1,2,3,3,2,1]
[1,2,3,2,3,1]
[1,2,3,2,1,3]
[1,2,2,3,3,1]
[1,2,2,3,1,3]
[1,2,2,1,3,3]
[3,3,1,2,1,2]
[3,1,3,2,1,2]
[3,1,2,3,1,2]
[3,1,2,1,3,2]
[3,1,2,1,2,3]
[1,3,3,2,1,2]
[1,3,2,3,1,2]
[1,3,2,1,3,2]
[1,3,2,1,2,3]
[1,2,3,3,1,2]
[1,2,3,1,3,2]
[1,2,3,1,2,3]
[1,2,1,3,3,2]
[1,2,1,3,2,3]
[1,2,1,2,3,3]
[3,3,1,1,2,2]
[3,1,3,1,2,2]
[3,1,1,3,2,2]
[3,1,1,2,3,2]
[3,1,1,2,2,3]
[1,3,3,1,2,2]
[1,3,1,3,2,2]
[1,3,1,2,3,2]
[1,3,1,2,2,3]
[1,1,3,3,2,2]
[1,1,3,2,3,2]
[1,1,3,2,2,3]
[1,1,2,3,3,2]
[1,1,2,3,2,3]
[1,1,2,2,3,3]

问题总共有90个解,即6!/2!2!2!.
~~~~~~~~~~~~~~~~~~~~~~~~~~
如何产生112233所有本质不同的排列?
我们首先定义两个排列的字典序:
a(1)a(2)…a(n)<b(1)b(2)…b(n) iff 存在k,1≤k≤n,使得a(1)=b(1),a(2)=b(2),…,a(k-1)=b(k-1)且a(k)<b(k)
一个排列称为基本解,如果它经过群S3元素及排列逆序变换反复作用后,不会变换为字典序更小的排列。
由于两次逆序变换将一个排列变成自身,因此,我们可以按照下面的方法来判断一个排列是否基本解:
(1)       在群S3元素的作用下,该排列字典序是否会减小?如果减小,则该排列不是基本解。判断的方法是:在排列中,1、2、3的首次出现次序是1在最前面,2其次,3在最后;
(2)       对排列进行逆序变换,然后将其最小化。所谓最小化,是指对逆序变换的排列进行变换(变换取自S3),使得1、2、3的首次出现次序按从小到大的次序排列。如果最小化后的排列比原排列字典序小,则原排列不是基本解。
对于上述问题进行手工验算。首先,我们考虑判断原则(1),则基本解只需在下面15个解中寻找:

[1,2,3,3,2,1]
[1,2,3,2,3,1]
[1,2,3,2,1,3]
[1,2,2,3,3,1]
[1,2,2,3,1,3]
[1,2,2,1,3,3]
[1,2,3,3,1,2]
[1,2,3,1,3,2]
[1,2,3,1,2,3]
[1,2,1,3,3,2]
[1,2,1,3,2,3]
[1,2,1,2,3,3]
[1,1,2,3,3,2]
[1,1,2,3,2,3]
[1,1,2,2,3,3]

利用判断原则(2),我们找到问题的11个基本解。
 
逆序变换
最小化变换
最小化结果
是否基本解?
123321
123321
(1)(2)(3)
123321
基本解
123231
132321
(23)
123231
基本解
123213
312321
(123)
123132
 
122331
133221
(23)
122331
基本解
122313
313221
(123)
121332
 
122133
331221
(123)
112331
 
123312
213321
(12)
123312
基本解
123132
231321
(132)
123213
基本解
123123
321321
(13)
123123
基本解
121332
233121
(132)
122313
基本解
121323
323121
(13)
121323
基本解
121233
332121
(13)
112321
 
112332
233211
(132)
122133
基本解
112323
323211
(13)
121233
基本解
112233
332211
(13)
112233
基本解
基本解的判断程序如下:
domains
 ilist=integer*
 ilists=ilist*
 tr=t(integer,integer)
 trlist=tr*
 
predicates
 nondeterm dup_perm(ilists, ilist)
 nondeterm dup_perm_3(ilists, ilist, ilist)
 nondeterm merge(ilist, ilist, ilist)
 
 nondeterm aabbcc(ilist)
 nondeterm is_primary_perm(ilist)
 nondeterm check1(ilist)
 nondeterm check2(ilist)
 
 nondeterm reverse(ilist, ilist)
 nondeterm reverse_3(ilist, ilist, ilist)
 
 nondeterm le(ilist, ilist)
 
 nondeterm s3(integer, trlist)
 nondeterm trans(trlist, ilist, ilist)
 nondeterm find_trans_member(tr, trlist)
 
clauses
 aabbcc(P):-
      dup_perm([[1,1],[2,2],[3,3]], P),
      is_primary_perm(P).
 
 is_primary_perm(P):-
      check1(P),
      check2(P).
 
 check1(P):-
      s3(1, T1), trans(T1, P, P1), le(P,P1),
      s3(2, T2), trans(T2, P, P2), le(P,P2),
      s3(3, T3), trans(T3, P, P3), le(P,P3),
      s3(4, T4), trans(T4, P, P4), le(P,P4),
      s3(5, T5), trans(T5, P, P5), le(P,P5),
      s3(6, T6), trans(T6, P, P6), le(P,P6).
 
 check2(P):-
      reverse(P,R),
      s3(1, T1), trans(T1, R, R1), le(P,R1),
      s3(2, T2), trans(T2, R, R2), le(P,R2),
      s3(3, T3), trans(T3, R, R3), le(P,R3),
      s3(4, T4), trans(T4, R, R4), le(P,R4),
      s3(5, T5), trans(T5, R, R5), le(P,R5),
      s3(6, T6), trans(T6, R, R6), le(P,R6).
 
 reverse(L, R):-reverse_3(L, [], R).
 
 reverse_3([H|L], T, R):-
    reverse_3(L, [H|T], R).
 reverse_3([], R, R).
 
 le([],[]).
 le([X1|_], [X2|_]):-X1 < X2.
 le([X|L1], [X|L2]):-le(L1, L2).
 
 s3(1, [t(1,1), t(2,2), t(3,3)]).
 s3(2, [t(1,1), t(2,3), t(3,2)]).
 s3(3, [t(1,2), t(2,1), t(3,3)]).
 s3(4, [t(1,2), t(2,3), t(3,1)]).
 s3(5, [t(1,3), t(2,1), t(3,2)]).
 s3(6, [t(1,3), t(2,2), t(3,1)]).
 
 trans(_, [], []).
 trans(T, [X|P1], [Y|P2]):-
      find_trans_member(t(X,Y), T),
      trans(T, P1, P2).
     
 find_trans_member(t(X,Y), [t(X,Y)|_]):-!.
 find_trans_member(t(X,Y), [t(Z,_)|T]):-
      X <> Z,
      find_trans_member(t(X,Y), T).
     
 
 dup_perm([], []).
 dup_perm([L|Ls], P):-dup_perm_3(Ls, L, P).
 
 dup_perm_3([], P, P).
 dup_perm_3([L|Ls], P0, P):-
      merge(L, P0, P1),
      dup_perm_3(Ls, P1, P).
     
 merge([], L, L):-!.
 merge(L, [], L):-!.
 merge([X|L1], L2, [X|L]):-merge(L1, L2, L).
 merge(L1, [X|L2], [X|L]):-merge(L1, L2, L).
 
goal
 aabbcc(P),
 write(P), nl,
 fail.
上述目标生成的全部11个解,这与我们分析的结果是一致的:
[1,2,3,3,2,1]
[1,2,3,2,3,1]
[1,2,2,3,3,1]
[1,2,3,3,1,2]
[1,2,3,1,3,2]
[1,2,3,1,2,3]
[1,2,1,3,3,2]
[1,2,1,3,2,3]
[1,1,2,3,3,2]
[1,1,2,3,2,3]
[1,1,2,2,3,3]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

上述程序是有局限的,我们枚举了S3的所有元素,并采用一种特殊的数据结构来简化问题求解的逻辑。如何将上述程序进行修改,使之适应于任意多重元素集合本质不同的排列的枚举,可以进一步探讨。但是上述程序适应于3个元素任意多重排列的情况,例如,当每个元素均为3重时,我们要求111222333本质不同的排列,可以修改aabbcc谓词为:
 aabbcc(P):-
      dup_perm([[1,1,1],[2,2,2],[3,3,3]], P),
      is_primary_perm(P).
程序运行生成全部148个解:

[1,2,2,2,1,3,3,3,1]
[1,2,3,2,1,3,3,2,1]
[1,2,3,2,1,3,2,3,1]
[1,2,2,3,3,1,3,2,1]
[1,2,2,3,3,1,2,3,1]
[1,2,2,3,3,1,2,1,3]
[1,2,2,3,1,3,3,2,1]
[1,2,2,3,1,3,2,3,1]
[1,2,2,3,1,3,2,1,3]
[1,2,2,3,1,2,3,3,1]
[1,2,2,1,3,3,3,2,1]
[1,2,2,1,3,3,2,3,1]
[1,2,2,1,3,3,2,1,3]
[1,2,2,1,3,2,3,3,1]
[1,2,2,1,2,3,3,3,1]
[1,2,3,3,2,1,1,2,3]
[1,2,3,2,3,1,3,1,2]
[1,2,3,2,3,1,1,3,2]
[1,2,3,2,3,1,1,2,3]
[1,2,3,2,1,3,3,1,2]
[1,2,3,2,1,3,1,3,2]
[1,2,2,3,3,3,1,1,2]
[1,2,2,3,3,1,3,1,2]
[1,2,2,3,3,1,1,3,2]
[1,2,2,3,3,1,1,2,3]
[1,2,2,3,1,3,3,1,2]
[1,2,2,3,1,3,1,3,2]
[1,2,2,3,1,3,1,2,3]
[1,2,2,3,1,1,3,3,2]
[1,2,2,1,3,3,3,1,2]
[1,2,2,1,3,3,1,3,2]
[1,2,2,1,3,3,1,2,3]
[1,2,2,1,3,1,3,3,2]
[1,2,2,1,1,3,3,3,2]
[1,2,3,3,1,2,2,3,1]
[1,2,3,3,1,2,2,1,3]
[1,2,3,1,3,2,3,2,1]
[1,2,3,1,3,2,2,3,1]
[1,2,3,1,3,2,2,1,3]
[1,2,3,1,2,3,3,2,1]
[1,2,3,1,2,3,2,3,1]
[1,2,3,1,2,3,2,1,3]
[1,2,1,3,3,3,2,2,1]
[1,2,1,3,3,2,3,2,1]
[1,2,1,3,3,2,2,3,1]
[1,2,1,3,3,2,2,1,3]
[1,2,1,3,2,3,3,2,1]
[1,2,1,3,2,3,2,3,1]
[1,2,1,3,2,3,2,1,3]
[1,2,1,3,2,2,3,3,1]
[1,2,1,3,2,2,3,1,3]
[1,2,1,2,3,3,3,2,1]
[1,2,1,2,3,3,2,3,1]
[1,2,1,2,3,3,2,1,3]
[1,2,1,2,3,2,3,3,1]
[1,2,1,2,3,2,3,1,3]
[1,2,1,2,2,3,3,3,1]
[1,2,3,1,3,2,3,1,2]
[1,2,3,1,3,2,1,2,3]
[1,2,3,1,2,3,3,1,2]
[1,2,3,1,2,3,1,3,2]
[1,2,3,1,2,3,1,2,3]
[1,2,1,3,3,3,2,1,2]
[1,2,1,3,3,2,3,1,2]
[1,2,1,3,3,2,1,3,2]
[1,2,1,3,3,2,1,2,3]
[1,2,1,3,2,3,3,1,2]
[1,2,1,3,2,3,1,3,2]
[1,2,1,3,2,3,1,2,3]
[1,2,1,3,2,1,3,3,2]
[1,2,1,3,2,1,3,2,3]
[1,2,1,2,3,3,3,1,2]
[1,2,1,2,3,3,1,3,2]
[1,2,1,2,3,3,1,2,3]
[1,2,1,2,3,1,3,3,2]
[1,2,1,2,3,1,3,2,3]
[1,2,1,2,1,3,3,3,2]
[1,2,1,3,3,1,2,2,3]
[1,2,1,3,1,3,2,2,3]
[1,2,1,3,1,2,3,3,2]
[1,2,1,1,3,3,2,3,2]
[1,2,1,1,3,3,2,2,3]
[1,2,1,1,3,2,3,3,2]
[1,2,1,1,3,2,3,2,3]
[1,2,1,1,2,3,3,3,2]
[1,2,1,1,2,3,3,2,3]
[1,1,2,3,3,3,2,2,1]
[1,1,2,3,3,2,3,2,1]
[1,1,2,3,3,2,2,3,1]
[1,1,2,3,3,2,2,1,3]
[1,1,2,3,2,3,3,2,1]
[1,1,2,3,2,3,2,3,1]
[1,1,2,3,2,3,2,1,3]
[1,1,2,3,2,2,3,3,1]
[1,1,2,3,2,2,3,1,3]
[1,1,2,3,2,2,1,3,3]
[1,1,2,2,3,3,3,2,1]
[1,1,2,2,3,3,2,3,1]
[1,1,2,2,3,3,2,1,3]
[1,1,2,2,3,2,3,3,1]
[1,1,2,2,3,2,3,1,3]
[1,1,2,2,3,2,1,3,3]
[1,1,2,2,2,3,3,3,1]
[1,1,2,2,2,3,3,1,3]
[1,1,2,3,3,3,2,1,2]
[1,1,2,3,3,2,3,1,2]
[1,1,2,3,3,2,1,3,2]
[1,1,2,3,3,2,1,2,3]
[1,1,2,3,2,3,3,1,2]
[1,1,2,3,2,3,1,3,2]
[1,1,2,3,2,3,1,2,3]
[1,1,2,3,2,1,3,3,2]
[1,1,2,3,2,1,3,2,3]
[1,1,2,3,2,1,2,3,3]
[1,1,2,2,3,3,3,1,2]
[1,1,2,2,3,3,1,3,2]
[1,1,2,2,3,3,1,2,3]
[1,1,2,2,3,1,3,3,2]
[1,1,2,2,3,1,3,2,3]
[1,1,2,2,3,1,2,3,3]
[1,1,2,2,1,3,3,3,2]
[1,1,2,2,1,3,3,2,3]
[1,1,2,3,3,3,1,2,2]
[1,1,2,3,3,1,2,3,2]
[1,1,2,3,3,1,2,2,3]
[1,1,2,3,1,3,2,3,2]
[1,1,2,3,1,3,2,2,3]
[1,1,2,3,1,2,3,3,2]
[1,1,2,3,1,2,3,2,3]
[1,1,2,1,3,3,3,2,2]
[1,1,2,1,3,3,2,3,2]
[1,1,2,1,3,3,2,2,3]
[1,1,2,1,3,2,3,3,2]
[1,1,2,1,3,2,3,2,3]
[1,1,2,1,3,2,2,3,3]
[1,1,2,1,2,3,3,3,2]
[1,1,2,1,2,3,3,2,3]
[1,1,2,1,2,3,2,3,3]
[1,1,1,2,3,3,3,2,2]
[1,1,1,2,3,3,2,3,2]
[1,1,1,2,3,3,2,2,3]
[1,1,1,2,3,2,3,3,2]
[1,1,1,2,3,2,3,2,3]
[1,1,1,2,3,2,2,3,3]
[1,1,1,2,2,3,3,3,2]
[1,1,1,2,2,3,3,2,3]
[1,1,1,2,2,3,2,3,3]
[1,1,1,2,2,2,3,3,3]

 
 
 
 
 
 
<think>我们使用pygame来检测键盘按键,因为pygame是一个常用的游戏开发库,它提供了丰富的键盘事件处理功能。 根据引用[4]提到,pygame不支持互动shell,但我们可以创建一个简单的窗口来检测按键事件。 步骤: 1. 初始化pygame 2. 创建一个窗口 3. 在事件循环中检测按键事件,特别是当按下'w'键时,输出字符串'aabbcc' 注意:我们不需要复杂的图形界面,只需要能够捕获按键事件即可。 代码示例: 我们将创建一个窗口,然后运行一个事件循环。当按下'w'键时,在控制台输出'aabbcc'。同时,我们设置一个退出条件(比如按下关闭按钮或ESC键)。 参考引用[4]中提到的“10行代码完成第一个pygame游戏窗口”,我们进行扩展。 但是注意,引用[4]并没有给出具体的10行代码,所以我们按照常规的pygame程序结构编写。 另外,根据引用[5]中使用了cv2,但这里我们不需要图像处理,只需要键盘事件,所以用pygame即可。 由于用户需求只是按下'w'输出字符串,我们不需要显示任何图形,但为了能够捕获键盘事件,pygame要求有一个窗口。 我们尽量简化窗口。 代码实现如下:</think>以下是使用 Python 检测按键 'w' 并输出 'aabbcc' 的解决方案: ### 使用 Pygame 检测按键 ```python import pygame import sys # 初始化 Pygame pygame.init() # 创建窗口(最小尺寸) screen = pygame.display.set_mode((200, 100)) pygame.display.set_caption("按键检测") # 主循环 while True: for event in pygame.event.get(): # 退出检测 if event.type == pygame.QUIT: pygame.quit() sys.exit() # 按键检测 if event.type == pygame.KEYDOWN: # 检测 'w' 键 if event.key == pygame.K_w: print("aabbcc") # 输出指定字符串 # 退出快捷键(ESC) if event.key == pygame.K_ESCAPE: pygame.quit() sys.exit() # 刷新显示(保持窗口响应) pygame.display.flip() ``` ### 代码说明 1. **初始化**:`pygame.init()` 初始化所有 Pygame 模块 2. **窗口设置**:创建 200x100 像素的最小化窗口 3. **事件循环**: - `pygame.KEYDOWN` 检测按键事件 - `pygame.K_w` 识别 'w' 键 - 按下 'w' 时执行 `print("aabbcc")` 4. **退出机制**: - 点击窗口关闭按钮 - 按 ESC 键退出程序 ### 运行效果 1. 运行程序后会出现小窗口 2. 当焦点在窗口时按下 'w' 键 3. 控制台将输出: `aabbcc` > **注意**:需要先安装 Pygame 库: > `pip install pygame` ### 备选方案:使用 keyboard 库(无需窗口) ```python import keyboard # 注册 'w' 键监听 keyboard.on_press_key('w', lambda _: print("aabbcc")) # 保持程序运行 keyboard.wait('esc') # 按 ESC 退出 ``` > **安装**:`pip install keyboard` > **限制**:部分系统可能需要管理员权限
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值