1、1排列与组合的应用四川成都市大弯中学 李植武摘要 在信息学奥林匹克竞赛中,多次出现了排列与组合的竞赛题目。本文介绍了排列与组合的概念、公式,重点讲解了排列与组合的生成算法,最后通过几个竞赛题目的解决,体现了排列与组合在信息学竞赛中的应用。关键词 排列 组合 生成 应用说明:本文中的 pascal 程序在 Lazarus v0.9.22 beta 下调试完成,c 程序 dev-c+ 4.9.9.2 下调试完成,所有程序通过相应数据测试。一、排列与组合 1排列及公式 (1)线排列一般地,从 n 个不同元素中,取出 m(mn)个元素按照一定的顺序排成一列,叫做从 n 个不同元素中取出 m 个元素的一
2、个线排列;从 n 个不同元素中取出 m(mn)个元素的所有线排列的个数,叫做从 n 个不同元素中取出 m 个元素的排列数,用符号 表示。 mnA)!( 1)-.(21n规定 0!1。(2)圆排列从 n 个不同元素中取出 m 个元素按照某种次序(如逆时针)排成一个圆圈,称这样的排列为圆排列,圆排列个数为 。)!(mnA因为从 n 个不同元素中取出 m 个元素排成一列的个数是 。不妨设一个排nA列是:a 1a2am。而这个排列与排列 a2ama1, a3ama1a2, ama1a2am-1,是一样的圆排列,共有 m 个,所以一个圆排列对应 m 个普通排列,所以有圆排列数 。An(3)无限重排列从
3、n 个不同元素中取 r 个元素按次序排列,每个元素可以取无限次,这样的排列称为无限重排列。显然,其排列数为 nr。(4)有限重排列从 k 个不同元素 a 1a2ak 中取 n 个元素按次序排列,元素 ai可以取 ri次,r 1+r2+.+rk =r,这样的排列称为有限重排列。实际上,这个问题与下面的问题等价:2把 r(r1+r2+.+rk =r)只彩色球放到 n 个编号不同的盒子中去的方法数。!.21krnA如 r=n,则排列数有 。!.!21krrn(5)错排问题一个排列使得所有的元素都不在原来的位置上,则称这个排列为错排。例如有 3 个元素,原来位置为:1 2 3,它的错排有两种 3 1
4、2 和 2 3 1。用 fn表示 n 个元素的错排数,利用容斥原理可以推出(过程略):fn= 。!1)(.!n主要讲一下递推式。考虑任意一个满足条件的排列 a1,a2,a3,an,显然有 ann,不妨设 n=ai,考虑书 i 的位置,它有两种情况:1)i=an2)ia n对于 1),数 i 在位置 n,而数 n 在位置 i 上,则是 n-2 的错排问题,这种情况的方法数为 fn-2。对于),可以把位置 n 看成位置 i(位置 i 上不放数 i,而此时位置 n 也不放数 i,所以 i 和 n 可以等同看待),则问题成了 n-1 个数的错排问题了。由 1)与 2)及 i 有 n-1 种取值,所以有
5、 fn=(n-1)(fn-2+fn-1)。:2组合及公式 (1)非重组合一般地,从 n 个不同元素中,取出 m(mn)个元素,不允许元素重复,不考虑元素次序,叫做从 n 个不同元素中取出 m 个元素的一个非重组合;从 n 个不同元素中取出 m(mn)个元素的所有组合的个数,叫做从 n 个不同元素中取出 m 个元素的组合数.用符号 表示. mnC1)!(!)1).(21(0nmnCA规 定组合数的两个性质: 11mnmnC(2)重组合3从 n 个不同元素中,取出 r 个允许重复的元素而不考虑其次序时,称为从 n个不同元素中取 r 个允许重复的组合,简称重组合。其组合数为. )!1(1Crn这个问
6、题,可以看作用 r 个相同的标记去标明这 n 个不同的对象,而每一个对象可以被标上多个标记,一个对象上最多 r 个标记。设 n 个元素为 a 1a2an ,记 ai被记了 k 次为 ai(k),同一个元素标记不同次数,认为是不同的元素,那么第 1 次标记有 n 种方法,有 n+1 个元素 a1a2an ai(k),第 2 次标记就有 n+1 种方法,有 n+2 个元素,第 r 次标记有 n+r-1 种方法,有 n-r 个元素,而标记顺序对结果没有影响,所以有种方法,即 。r!1)-()( )!1(1nrCrn二、排列与组合生成算法1.排列生成有 N 本不同的书摆在书架上,设其编号分别为, .,
7、编程求解这本书的不同摆放方案和摆放方案总数。程序名:pailie.pas/c/cpp 输入文件:pailie.in 输出文件: pailie.out输入文件的格式为:仅为一个数 N输出文件的格式为:依次为每一行为一种方案,每个数之间用一个空格隔开,最后一行为方案数样例input2output1 22 12数据规模 1=1)and(ai-1ai) do dec(i);fi:=i;end;function fk:longint;vark:longint;begink:=n;while (k1)and(ak1 dobegink:=fk;t:=ai-1;ai-1:=ak;ak:=t;for j:=i
8、to (n+i)div 2 dobegin5t:=an+i-j;an+i-j:=aj;aj:=t;end;print;i:=fi;end;writeln(s);close(input);close(output);end.()回溯算法产生排列用 pi记录一个排列的第 i 个数, 没 有 用 已 用 ifalsetruia伪代码描述的产生排列的第 i 个数的方法Procedure try(i)BeginIf in then begin 输出排列;返回 end;/产生了一个完整排列,输出For j=1 to n do If not aj then / j 这个数没有用Begin Pi=j;Aj=t
9、rue; /占位Try(i+1); /搜索下一个数End;End;Pascal 版参考程序:program pailie;varp:array1.10 of longint;a:array1.10 of boolean;n,tot,i:longint;fil:text;procedure print;vari:longint;begininc(tot);for i:=1 to n dowrite(fil,pi, );writeln(fil);end;6procedure tryy(i:longint);varj:longint;beginif in then begin print;exit
10、end;for j:=1 to n doif not aj thenbeginaj:=true;pi:=j;tryy(i+1);aj:=false;end;end;beginassign(fil,pailie.in);reset(fil);readln(fil,n);close(fil);assign(fil,pailie.out);rewrite(fil);fillchar(a,sizeof(a),false);tot:=0;tryy(1);writeln(fil,tot);close(fil);end.C 语言版参考程序:# include long a15,n,s;bool f15;FI
11、LE *fp;void shu(long a)long i;for (i=1;i0) and (ci=n-(r-i) do dec(i);findi:=i;end;beginassign(fil,zuhe.in);reset(fil);readln(fil,n,r);close(fil);for i:=1 to r do ci:=i;assign(fil,zuhe.out);rewrite(fil);tot:=0;repeatprint;i:=findi;if i0 thenbegininc(ci);for j:=i+1 to r do cj:=cj-1+1;end;until i=0;wri
12、teln(fil,tot);close(fil);end.()回溯算法产生组合用i 记录一个组合的第 i 个数, 9伪代码描述产生组合第 i 个数的方法Procedure try(i,last) /last 表示第 i-1 个数的取值BeginIf ir then begin 输出组合;返回 end;/产生了一个完整组合,输出For j=last+1 to n do Begin ci=j;Try(i+1,j); /搜索下一个数End;End;Pascal 版参考程序:program zuhe;varc:array1.30 of longint;n,r,i,j,tot:longint;fil:t
13、ext;procedure print;vari:longint;begininc(tot);for i:=1 to r dowrite(fil,ci, );writeln(fil);end;procedure tryy(i,last:longint);varj:longint;beginif ir then begin print;exit; end;for j:=last+1 to n dobeginci:=j;tryy(i+1,j);end;end;beginassign(fil,zuhe.in);reset(fil);readln(fil,n,r);close(fil);assign(
14、fil,zuhe.out);rewrite(fil);tot:=0;tryy(1,0);10writeln(fil,tot);close(fil);end.C 语言版参考程序:# include long a35,n,s,r;FILE *fp;void shu(long a)long i;for (i=1;i=r;i+)fprintf(fp,“%d “,ai);fprintf(fp,“n“);s+; void pai(long i,long k)long j;if (i=r+1) shu(a); return ; for (j=k;j=n;j+) ai=j; pai(i+1,j+1); int main()long i,j,k,m;fp=fopen(“zuhe.in“,“r“);fscanf(fp,“%d %d“,fp=fopen(“zuhe.out“,“w“);s=0; pai(1,1);fprintf(fp,“%dn“,s);fclose(fp);return 0;三、排列与组合应用1.火星人(noip2004 普及组)【问题描述】人类终于登上了火星的土地并且见到了神秘的火星人。人类和火星人都无法理解对方的语言,但是我们的科学家发明了一种用数字交流的方法。这种交流方法是这样的,首先,火星人把一个非常大的数字告诉人类科学家,科学家