- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
显然a1=b1,如果一直到an-1 =bn-1,定理得证:
否则令k=min{i,ai≠bi }, 那么: ai=bi ,当i<k时
a i! b i!
i i ik ik
n 1
n 1
如果两边同时除以(k+1)! 我们可以看到等式左边余数为akk! 等式右边余数为bkk! 由ak≠bk,与假设予盾,因此表示法是唯一的。
11
一、序数法
怎样建立a(3)a(2)a(1)p(1)p(2)p(3)p(4)
a(3) 确定4的位置,a(2)确定3的位置
a(1)确定2的位置,剩余的位置就是1的位置 例3:021, 3 2 1 4 例3: 201, 2 4 1 3
12
一、序数法
求n个不同的数的全排列,主要有以下两步:
1、求出0到n!-1之间各数对应的序列{an-1, an-2,…, a1} m=an-1(n-1)!+an-2(n-2)!+…a2 * 2!+a1*1! 2、由{an-1, an-2,…, a1}确定排列序列p1p2…pn an-1,确定n的位置, an-2确定n-1的位置, ……………………… a1确定2的位置, 剩下的是1的位置。
10
一、序数法
例2:对于0 m 23=4!-1,m可以展开为: m=a33!+a2 2!+a1 1!。 求所有的序列{a3, a2,a1} ; 解: 0000, 4020, 8110, 12101, 16220, 20301, 1001, 5021, 9111, 13201, 17221, 21311, 2010, 6100, 10120, 14210, 18300, 22320, 3011, 7101, 11121, 15211 19301, 23321
20
二、字典序法
例4:求839647521的下一个排列。
1:从排列的末尾开始,逐步向前搜索,直到找到比 其后面相邻的数小的数:
如果未找到,表明不再有下一个排列,程序终止; 2:从该数后面的序列中寻找比该数大的最小的 数来替换它(使用交换); 3:将余下的数反转。
21
二、字典序法
1、求满足关系式pj<pj+1的下标j的最大值,设为 i , i=max{j︱pj<pj+1} 例如: 839647521中i=5 注:该位置值为4 2、求出i后,再求满足关系式pi<pk的k的最大值, 设为h, h=max{k︱pi<pk} 例如: 839647521中h=7 注:该位置值为5 3、 pi与ph 互换。得新排列P1P2…Pi-1PiPi+1…Pn 例如: 839647521换成839657421
5
一、序数法
定理3:令n0,0≤m≤n!-1,则m可以唯一地表 示为:m=an-1(n-1)!+an-2(n-2)!+…+a11! 其中:0aii, i=1, 2, …, n-1。(一) ai由m唯一确定。 (二) 反过来,任何满足上式的数m都是一个大于或 等于0,小于或等于n!-1的数。 (三)
17
一、序数法
void main() { int n; cout << "请输入一个数"; cin >> n; permute(n); }
*
18
二、字典序法
字典序法的思想:
对于n个字符的任何二个排列,我们都可以 比较它的大小。 1、初始排列我们可以给出来, 1,2,3,…,n-1,n 2、设计算法找到比上一个排序大的排列中最 小的一个。 1,2,3,…,n,n-1
14
一、序数法
2、对于0,1,2,…,n!-1共n!个数求序列a[i]
for( i = 0; i < fact; i++ ) { int b=i, index =1; do { a[index]=b%(index+1); b = b/(index+1); index++; } while(b);
15
一、序数法
3、a[j]确定j+1的位置 int j=0; for(j=n-1;j>0;j--) {index=n; int spacecount=0; while(a[j]>spacecount||result[index]!=0) { if( result[index]==0) spacecount++; index--; } result[index]=j+1; }
16
一、序数法
//最后一个位置是1的位置 index = n; while( result[index]!= 0) index--; result[ index ] = 1; // 输出结果 for( j = 1; j <= n; j++ ) { cout << result[ j ] << endl; result[ j ] = 0; } }}
27
1.6.4 组合的生成算法
1、最后一位数最大是6,倒数第二位最大 是5,倒数第三位最大是4。
若r个元素组合用c1c2… cr表示,假定 c1<c2<…<cr那么cr≤n, cr-1≤n-1,… c1≤n-r+1 2、若要确定145的下一个组合, 就是要找比145大而又最接近 145的数, 那么256的下一个组合是什 么呢? 显然是146; 是345。
13
一、序数法
1、求阶乘 int result[17] = { 0 }; //记录排序 int a[17] = { 0 }; //记录序列 void permute( int n) { int fact = 1,i; for( i = 1; i <= n; i++ ) fact *= i;//求n的阶乘
7
一、序数法
证明:(一)可表示性
怎样求序列{an-1, an-2,…, a1} m=an-1(n-1)!+an-2(n-2)!+…+a2 2!+ a1 1! 数m除以2的整数部分与余数是什么? 整数部分是:an-1(n-1)!/2+… +a3 3!/2 +a2 余数是a1 如果用m除以2的整数部分再除以3,余数就 是a2,其它项以此类推。
3、重复以上过程直到最大。 n,n-1,…,3,2,1
19
二、字典序法
例4:求839647521的下一个排列。
只要后边的大数与前面的小数交换,都比原 数大,那个是最小的一个。 这一个与下一个有尽可能长的共同前缀,也 即变化限制在尽可能短的后缀上。 找到前面数小于后边数的最后一个,4 4与后面比它大最接近他的数交换,5 此时5右边为7421,倒置为1247,即得下一 个排列:839651247。
3
一、序数法
序数法的思想: n个元素的全排列有n!个,从0到n!-1共n!个数。
n个元素的全排列与n!个数一一对应。
序数法找到了一种n!个数直接计算出n!个排列的 算法: 1、0到n!-1这n!个数与如下序列一一对应: (an-1,an-2,…a1) 0aii; 2、从每一个这样的序列我们可以生成一个排列。
第一章:排列与组合 1.1 基本计数法则 1.2 一一对应:
1.3 排列与组合
1.4 圆周排列
1.5 排列的生成算法
1.6 允许重复的组合与不相邻的组合
1.7 组合意义的解释
1.8 应用举例 1.9 *Stirling公式
1
1.5 排列的生成算法:
排列的生成算法:
对于给定的字符集,用有效的方法将所有 可能的排列无重复无遗漏地枚举出来。 3阶幻方 九宫图 8(a11) 1 (a12) 6 (a13)
观察从1,2,3,4,5,6中取3个的组合,找出规律 (1)123, (2)124, (3)125, (4)126, (5)134 (6)135, (7)136, (8)145, (9)146, (10)156 (11)234, (12)235, (13)236, (14)245, (15)246, (16)256, (17)345, (18)346, (19)356, (20)456
4
一、序数法
公式: n!-1=(n-1)(n-1)!+(n-2)(n-2)!+…+2×2!+ 1×1!
等同于: n!=(n-1)(n-1)!+(n-2)(n-2)!+…+2×2!+ 1×1!+1 一般: (k-1)×(k-1)!+(k-1)!=k! ……………………………… (n-2)(n-2)!+(n-2)!=(n-1)! (n-1)(n-1)!+(n-1)!=n!
最小值是: 0×(n-1)!+0×(n-2)!+…+ 0×1!=0 最大值是: (n-1)(n-1)!+(n-2)(n-2)!+…+2×2!+ 1×1!=n!-1 因此:(三)成立
6Hale Waihona Puke 一、序数法证明:(二)唯一表示性
设m=an-1(n-1)!+an-2(n-2)!+…+a11! m=bn-1(n-1)!+bn-2(n-2)!+…+b11!
9
一、序数法
推论 从0到n!-1的n!个整数与序列{an-1, an-2,…, a1} 一一对应。这里 0a1 1,0 a2 2, …, 0 an-1 n-1 算法: int a[]={0}; int m,n;// 0=<m<=n!-1 int b=m; int index =1; do { a[index]=b%(index+1); b = b/(index+1); index++; } while(b);