当前位置:首页
开发技术指南» 文章正文
    引言:

    摘要: <?xml version="1.0" encoding="utf-8"?> <!doctype wml public "-//wapforum//dtd wml 1.3//en" "http://www.wapforum.org/dtd/wml13.dtd"> <wml> ......
    摘要: 太懒! ......


【高级擂台】72绝技

 
        少林寺有72绝技,有一天,方丈想把这些绝技传给他的弟子们。和尚们并不关心能学多少种绝技,而只关心自己所学的几项绝技是不是有人全部掌握。因为任何一种绝技只要练好了都能立于不败之地。比如和尚A会第项绝技,而B会第项绝技,A并不会感到师傅不公,因为他有一项绝技1,B不会。假设方丈大师会n项绝技,请你帮他算一算,在满足上面条件的情况下,他最多能传授几个弟子?

NO.1   作者: jettylee

忘记组合怎么算了~  
  大概是  
    n/2  
  C  
    n

NO.2   作者: Alonefield

To   jettylee  
  怎么证啊?

NO.3   作者: zlf_jack

introductory   combinatorics上面有详细证明!

NO.4   作者: zlf_jack

发信人:   starfish   (好好学习,天天向上),   信区:   Algorithm  
  标     题:   [合集]请教starfish一道离散题  
  发信站:   南京大学小百合站   (Fri   Jun   20   13:13:42   2003)  
   
  globus   (Every   Jack   has   his   Jill.)   于Fri   Jun   13   19:16:44   2003)  
  提到:  
   
  A是X=的一族子集构成的集合,其中的元素互不包含  
   
  证明   A的元素个数最大为Cn  
   
   
   
  starfish   (好好学习,天天向上)   于Fri   Jun   13   19:19:26   2003)  
  提到:  
   
  Cn表示什么啊?组合数?  
   
   
   
   
  globus   (Every   Jack   has   his   Jill.)   于Fri   Jun   13   19:22:36   2003)  
  提到:  
   
  是啊    
   
  就是选择嘛    
   
   
   
   
  cornucopia   (仰视星辰)   于Fri   Jun   13   20:40:14   2003)  
  提到:  
   
  取元素的方法必须就是Cn    
  但证明其他方法没他多。。。。  
  没想好呢,呵呵  
   
   
   
  globus   (Every   Jack   has   his   Jill.)   于Fri   Jun   13   22:09:38   2003)  
  提到:  
   
  这个凭常理判断    
   
  显然是每个元素都是一个包含n/2个数的集合的时候这样的元素最多  
   
  但是怎么证明呢?  
   
   
   
  starfish   (好好学习,天天向上)   于Fri   Jun   13   22:23:38   2003)  
  提到:  
   
  显然阿,  
   
  关键就在于证明当A中的每个元素势都相等的时候A中元素数目可以达到最多,  
   
  不过我也还没想到如何证明:$  
   
   
   
   
  sunder   (爱情不老)   于Sat   Jun   14   00:48:55   2003)  
  提到:  
   
  这样的集合称为杂置。  
  原题为Sperner定理:  
  令X为n个元素的集合。则X的杂置最多含有nC[n/2]个元素。  
   
  下面的证明来自Richard   A.   Brualdi的“Introductory   Combinatorics”第三版  
  国内有机械工业出版社出版的翻译版《组合数学》。  
   
  证明可使用归纳法,证明下面的更强的结论:  
   
  X的所有2^n个组合的集合可以被划分成nC[n/2]部分,使得任意杂置最多含有每一部分中的  
  一个组合。  
   
  此划分称为链划分  
   
  n=1时有1条  
  空集<{1}  
   
  n=2时有2条  
  空集<{1}<{1,2}  
  {2}  
   
  n=3时有3条  
  空集<{1}<{1,2}<{1,2,3}  
  {2}<{2,3}  
  {3}<{1,3}  
   
  通过对n=3所示的链划分得出对于n=4的组合的链划分如下  
  取多于一个组合的每一个链,做成n=4的两条链:  
  其一是通过把4加到原链的最后一个组合中得到一个新的组合,再将这个组合加到该链的最  
  后形成一条新链,另一个则是通过把4添加到原链除最后一个组合外的所有组合中得到。  
   
  链   "   空集<{1}<{1,2}<{1,2,3}   "  
  变成   "   空集<{1}<{1,2}<{1,2,3}<{1,2,3,4}   "   和   "   {4}<{1,4}<{1,2,4}   "  
  链   "   {2}<{2,3}   "  
  变成   "   {2}<{2,3}<{2,3,4}   "   和   "   {2,4}   "  
  链   "   {3}<{1,3}   "  
  变成   "   {3}<{1,3}<{1,3,4}   "   和   "   {3,4}   "  
   
  这样得到n=4的组合的6=4C2个链的一个链划分。在n=4的这个划分中,这些链有两个特殊的  
  性质。链中的每个组合都比它在链中的前趋组合多一个元素。链中  
  的第一个组合的大小加上该链的最后一个组合的大小是n=4.   类似性质对于n=1,2和3时的链  
  划分也是成立的。集合{1,2,。。。,}的组合的链划分如果  
          1)   链中的每个组合都比他在链中的前趋组合多一个元素;并且  
          2)链中的第一个组合的大小加上该链的最后一个组合的大小是n  
  则该链划分就是   对称的链划分。在对称链划分中的每一个链都恰好含有一个|_n/2_|组合  
  ,因此对该对称链划分中链的个数是为  
             
  nC[n/2](下取整)=nC[n/2](上取整)  
   
  正如上面对于n=3所述的那样,对于|1,2,...,n|的对称的链分解可以从{1,2,...n-1}的对  
  称的链分解归纳得到。    
  在{1,2,...n-1}的对称的链划分中,取任一个链  
  A1<A2<...<Ak,其中|A1|+|Ak|=n-1  
  并按照k=1还是k>1得到   {1,2,...,n}的一个或是两个链:  
  A1<A2<...<Ak<Ak+{n},其中|A1|+|Ak+{n}|=n  
  和  
  A1+{n}<...<Ak-1+{n},其中|A1+{n}|+|Ak-1+{n}|=n(如果k=1,则此链不出现)。    
  {1,2,...,n}的每一个组合恰好出现在用这种方法构造的一个链中,因此链的最后结果的  
  集合形成对于{1,2,...,n}的一个对称的链划分。  
  在{1,2,...,n}的对称的链划分中链的个数是  
   
  nC[n/2]  
   
  因此,在{1,2,...,n}的杂置中的组合的个数最多等于  
   
  nC[n/2]  
   
  如果n是偶数,可以证明,只有S的所有的n/2组合的杂置才是大小为   nC(n/2)   的杂置。  
   
  如果n是奇数,只有S的所有的(n-1)/2组合的杂置和所有的(n+1)/2组合的杂置才是那些这  
  样大小的杂置。  
   
   
   
  today   (俺家丢了只小狗)   于Sat   Jun   14   00:55:06   2003)  
  提到:  
   
  声明!!!:  
  这么长是一下一下打上去的,sunder打的太慢了,  
  所以后半部是我负责的。  
   
  害得我少灌了一会儿水,在这里灌一篇补偿一下。  
   
   
   
  ihappy   (听故事)   于Sat   Jun   14   00:59:46   2003)  
  提到:  
   
  这个翻译真是太糟糕了,看得难受死了  
   
  http://www.cut-the-knot.com/pigeonhole/sperner.shtml  
   
  这是一个英文的证明,很好懂的  
   
  btw,这个定理曾经作为某年高中数学联赛的题目  
   
   
   
  today   (俺家丢了只小狗)   于Sat   Jun   14   01:00:13   2003)  
  提到:  
   
  是啊,sunder也说翻译是很糟糕。  
   
   
   
  starfish   (好好学习,天天向上)   于Sat   Jun   14   01:02:30   2003)  
  提到:  
   
  完了  
   
  高中题目我都做不出来了,5555~~~~  
   
   
   
   
  ihappy   (听故事)   于Sat   Jun   14   01:05:20   2003)  
  提到:  
   
  hehe,没关系,当年我参加高中联赛的时候也没有做出来.  
   
  这种couting的题目想不到路子上怎么也做不出来的  
   
   
   
  today   (俺家丢了只小狗)   于Sat   Jun   14   01:06:58   2003)  
  提到:  
   
  ihappy你这就不对了,  
  你那时候是高中,他是研究生内,  
  而且你做不出来并不代表别人也应该做不出来呢。  
   
   
   
  starfish   (好好学习,天天向上)   于Sat   Jun   14   01:09:58   2003)  
  提到:  
   
  谢谢你的安慰  
   
  另外那个网站很不错  
   
  有不少好玩的东西:)  
   
   
   
   
  starfish   (好好学习,天天向上)   于Sat   Jun   14   01:10:29   2003)  
  提到:  
   
  FT~  
   
  再一次打击我~~  
   
  哐当  
   
   
   
   
  ihappy   (听故事)   于Sat   Jun   14   01:17:11   2003)  
  提到:  
   
  ft,你没有听说过这种竞赛题高中生能做出来,很多数学家却不行吗?  
   
  today分明是在挑拨离间,不要理她,呵呵.  
   
  today,kkkickkk,   现在给你一个将功赎罪的机会,到数学版去给我那个题目想一个  
  小学生能理解的解法.  
   
   
   
  sunder   (爱情不老)   于Sat   Jun   14   01:18:38   2003)  
  提到:  
   
  不仅糟糕  
  还有错误  
   
   
  borntolose   (天生是输家)   于Sat   Jun   14   05:54:14   2003)  
  提到:  
   
  人本来是越年轻越聪明。就像桃谷六仙说的,高中生比数学家聪明,三岁小孩比高中生聪  
  明,两岁小孩又比三岁小孩更聪明,......没出娘胎之前最聪明。:=)  
   
   
   
   
  globus   (Every   Jack   has   his   Jill.)   于Sat   Jun   14   10:08:20   2003)  
  提到:  
   
  哈哈  
   
  谢谢以上各位  
   
   
   
  cjs   (BlueSky)   于Sat   Jun   14   18:21:47   2003)  
  提到:  
   
  显然,计算机方面还是年轻人的天下。  
   
   
   
  today   (俺家丢了只小狗)   于Sat   Jun   14   22:09:28   2003)  
  提到:  
   
  倒~~~可是你不会做的也并不说明我能够做出来呀~~~  
 

NO.5   作者: lamanmi

收藏一下

NO.6   作者: ChinaPlayer

应该不会超过1000个吧?

NO.7   作者: delphi_xizhousheng

数学归纳法:  
  当N=2时:C(1,2)=2;//收两个  
  当N=3时:C(2,3)=C(1,3);     //C(2,3)表示每人教两门,C(1,3)表示每人教1门  
  当N=4时:C(1,4)=C(3,4)=4;   C(2,4)=6;//取C(2,4)   //每人教两门;  
  当N=4时:C(1,5)=C(4,5)=5;   C(2,5)=C(3,5)=10;//取C(2,4)   //每人教两门;  
   
  可以证明:C([n/2],n)是N的所以组合数中最大的,所以最后结果应该是C([n/2],n)  
 

NO.8   作者: delphi_xizhousheng

证明如下:  
   
  设R=Max(C(k,n));     (k<n);这个假设应该没有问题:-)  
  我们来看看   C(k,n)的最大值,展看C(k,n)=n*(n-1)*(n-2)......*(n-k+1)/k!=  
  n*(n-1)*(n-2)......*(n-k+1)/k*(k-1)*(k-2)......*1;这个没有问题吧:-)  
   
  展开式n*(n-1)*(n-2)......*(n-k+1)中共有K个乘法项,k!也是K个乘法项,所以  
  C(k,n)=n*(n-1)*(n-2)......*(n-k+1)/k*(k-1)*(k-2)......*1;  
  分子,分母都乘(n-k)!,得到C(k,n)=n*(n-1)*(n-2)......*(n-k+1)*(n-k)!/k*(k-1)*(k-2)......*1*(n-k)!     ;分子等于n!,分母等于k!*(n-k)!;  
  R最大,就是求k!*(n-k)!最小,就是在k!*(n-k)!最小时,k的取值就表示每个徒弟教k门时,收的徒弟最多!  
 

NO.9   作者: dengsf

楼上要首先证明,互不包含的子集数的最大值是C。  
  大体步骤:  
  首先猜测结果为   C  
  明显有如下结论:  
          对   i<j,   Si   里的每一个元素   必然   被包含于   Sj   里的一个或多个元素。********(结论1)  
   
          从   S1   的所有子集开始,如果   Sk   的元素被包含于   Sk+1   的某个元素,则以被包含的那个   Sk   的元素为起点画一有向边指向包含它的那个Sk+1里的元素,显然这是个层次结构很明显的图形。  
    A->B,将A叫做B前驱,的B叫做A的后继。  
    某一层的结点数最多的是   C([n/2],n)。  
          对于某个非空的子集,它对应于该图形的某个节点。  
   
  ~~~~~~~~~~~映射证明~~~~~~~~~~~  
          对于多个互不包含的子集,则一定可以将层数   k   !=   n/2   的那些结点映射到   第   n/2   层里去,并且保持它们互不包含性质不变。  
   
          因为对于   k<n/2   的层的任何结点,它们必然   被包含于   n/2层   的某些结点里(根据结论1)。  
          本身在第   n/2   层的的节点必不在这些节点当中,不然就违反了互不包含的前提;  
          这些结点也不存在到   >n/2   层   的那些结点的路径,否则根据传递关系,也违反前提。  
   
          而在这些节点当中,必然可以选出跟   层数<n/2   的节点一一对应并互不相同的的节点。方法是从最小的层数开始,向   n/2   方向逐层选出替代结点。  
          比如最小的层数k上   有个结点,则该结点在   k+1   层有多个后继,可以选择其中一个,并且:  
          这跟本身在k+1层的的结点不会相同,否则违反互不包含前提;  
          对于同是第k层的结点的,也可以做到不造成冲突。因为   到达   n/2   之前,每个节点的后继都   >1   个,对于   第   k   层互不相同的   x   个结点,它们共有   >x   个不同后继,画个图规范描叙就很简单地知道如何选择,这些看起来简单叙述麻烦的东西最吃力不讨好了,免去。   :

呕吐,居然做了吃力不讨好的事情……TT

NO.11   作者: gyhyq

经过计算为4.72236648286965E+21

NO.12   作者: gyhyq

-------------------------------------------------------------------------------------  
  创建日期:     2004-01-13  
  更新日期:     2004-09-14  
  创   建   者:     gyhyq  
  功能说明:     求解  
  少林寺有72绝技,有一天,方丈想把这些绝技传给他的弟子们。  
  和尚们并不关心能学多少种绝技,而只关心自己所学的几项绝技  
  是不是有人全部掌握?因为任何一种绝技只要练好了都能立于不败  
  之地。比如和尚A会第项绝技,而B会第项  
  绝技,A并不会感到师傅不公,因为他有一项绝技1,B不会。假设方丈  
  大师会n项绝技,请你帮他算一算,在满足上面条件的情况下,他最多能传授几个弟子?  
  -------------------------------------------------------------------------------------  
   
  Private   Sub   Command1_Click()  
          Dim   intRs   As   Double  
          计算  
            intRs   =   ComputResult  
            Text1.Text   =   intRs  
  End   Sub  
   
  功能:求解  
  输入:无  
  返回:结果  
  Private   Function   ComputResult()   As   Double  
          Dim   dblSum   As   Double  
          Dim   intN   As   Integer           绝技个数  
          72绝技  
          intN   =   72  
          For   i   =   1   To   intN  
                  dblSum=dblSum+计算C(n,m)  
                  dblSum   =   dblSum   +   ComputC(intN,   i)  
          Next  
          ComputResult   =   dblSum  
  End   Function  
   
  功能:计算n!/(m!(n-m)!)  
  输入:intN--N,intM--M  
  返回:结果  
  Private   Function   ComputC(ByVal   intN   As   Integer,   ByVal   intM   As   Integer)   As   Double  
          Dim   intNJc()   As   Integer           n!  
          Dim   intMJc()   As   Integer           m!  
          Dim   intNMJc()   As   Integer         (n-m)!  
          Dim   intFM()   As   Integer         (m!(n-m)!)  
           
          取N!数组  
          intNJc   =   IntToStr(intN)  
          取M!数组  
          intMJc   =   IntToStr(intM)  
          取(N-M)!数组  
          intNMJc   =   IntToStr(intN   -   intM)  
          计算(M!(N-M)!)  
          intFM   =   StrAndStr(intMJc,   intNMJc)  
          计算N!/(M!(N-M)!)  
          ComputC   =   StrDevStr(intNJc,   intFM)  
  End   Function  
   
  功能:将阶乘放入数组  
  输入:intNum-阶乘数字  
  返回:阶乘数组  
  Private   Function   IntToStr(ByVal   intNum   As   Integer)   As   Integer()  
          Dim   intVal()   As   Integer  
          如果为0则赋值1  
          If   intNum   =   0   Then  
          定义数组大小  
          ReDim   intVal(0)  
          intVal(0)   =   1  
          返回  
          IntToStr   =   intVal  
          Exit   Function  
          End   If  
           
          定义数组大小  
          ReDim   intVal(intNum   -   1)  
          For   i   =   0   To   intNum   -   1  
                  数组[i]=i  
                  intVal(i)   =   i   +   1  
          Next  
          返回  
          IntToStr   =   intVal  
  End   Function  
   
  功能:将两个阶乘数组相加  
  输入:strA()--第一个数组,strB()--第二个数组  
  返回:合并后的阶乘数组  
  Private   Function   StrAndStr(strA()   As   Integer,   strB()   As   Integer)   As   Integer()  
          Dim   strCount   As   Integer  
          Dim   strAB()   As   Integer                 合并后的数组  
          Dim   intLenA   As   Integer  
          Dim   intLenB   As   Integer  
          intLenA   =   UBound(strA)   +   1  
          intLenB   =   UBound(strB)   +   1  
          取合并后的长度  
          strCount   =   intLenA   +   intLenB   -   1  
          定义合并后的数组长度  
          ReDim   strAB(strCount)  
          将第一个数组放入  
          For   i   =   0   To   intLenA   -   1  
                  strAB(i)   =   strA(i)  
          Next  
          将第二个数组放入  
          For   i   =   0   To   intLenB   -   1  
                  strAB(i   +   intLenA)   =   strB(i)  
          Next  
          返回  
          StrAndStr   =   strAB  
  End   Function  
   
  功能:计算N!/(M!(N-M)!)  
  输入:strA()--分子数组,strB()--分母数组  
  返回:结果  
  Private   Function   StrDevStr(intA()   As   Integer,   intB()   As   Integer)   As   Double  
          Dim   dblAJc   As   Double  
          Dim   dblBJc   As   Double  
          取intA(i)中的数字  
          For   i   =   0   To   UBound(intA)  
                  取intB(j)中的数字  
                  For   j   =   0   To   UBound(intB)  
                          if   intA(i)中的数字等于intB(j)中的数字  
                          If   intA(i)   =   intB(j)   Then  
                                  则intA(i)与intB(j)中的数字为1  
                                  intA(i)   =   1  
                                  intB(j)   =   1  
                                  Exit   For  
                          End   If  
                  Next  
          Next  
          取intA中的积  
          dblAJc   =   StrAmass(intA)  
          取intB中的积  
          dblBJc   =   StrAmass(intB)  
          返回intA积/intB积  
          StrDevStr   =   dblAJc   /   dblBJc  
  End   Function  
   
  功能:求数组的积  
  输入:intNum()--数组源  
  返回:结果  
  Private   Function   StrAmass(intNum()   As   Integer)   As   Double  
          Dim   dblSum   As   Double  
          dblSum   =   1  
          求积  
          For   i   =   0   To   UBound(intNum)  
                  dblSum   =   dblSum   *   intNum(i)  
          Next  
          StrAmass   =   dblSum  
  End   Function  
   
 

NO.13   作者: hyena041

我喜欢这个vb的算法,呵呵  
  很少有人用vb回答问题的  
  commandbutton1.click!!^^


 ·u盘大家给推荐一个    »显示摘要«
    摘要: 超级稳定,即使3米自由落体都没事! 价格不是问题,要硬件加密的。样子好看,黑色最好!!! ......
» 本期热门文章:
· 热门栏目:
» 相关精选文章
» 其它相关:

©2000-2007 All Rights Reserved. 最佳浏览:1024X768 MSIE