zoukankan      html  css  js  c++  java
  • 由约瑟夫问题到一类特殊的递归式

    由约瑟夫问题到一类特殊的递归式

    参考资料:《具体数学》


    前言:

    其实。。本文和约瑟夫问题没什么关系。。题目是吸引你点进来的


    正文:

    约瑟夫问题

    这个,大家应该都知道吧,不知道的可以看一看这个

    下面是约瑟夫问题的一个简化版本:

    有n个人围成一个环,依次编号为1到n,然后1,2报数,报到2的人出列,求最后出列的人的编号。

    首先,我们打表找规律一下,规定J(n)表示n个人的约瑟夫问题中最后出列的人的编号。

    n J(n)
    1 1
    2 1
    3 3
    4 1
    5 3
    6 5
    7 7
    8 1
    9 3
    (cdots) (cdots)

    好像,全是奇数?

    其实,在第一轮时,转一圈后所有的偶数都出列了,剩下的当然只有奇数。

    那么我们考虑一下转一圈后的情况:

    当n为偶数时,转一圈删掉了n后又回到了1号,这时,原来编号为i的人的位置现在的人的编号变成了2*i-1,所以我们可以得到:

    [J(2n)=2J(n)-1 ]

    当n为奇数时,转一圈删掉了n-1后又删掉了1号,来到了3号,这时,原来编号为i的人的位置现在的人的编号变成了2*i+1,所以我们可以得到:

    [J(2n+1)=2J(n)+1 ]

    综合以上内容,我们可以得到下面的式子:

    [J(1)=1 ]

    [J(2n)=2J(n)-1 ]

    [J(2n+1)=2J(n)+1 ]

    有了这个式子,我们就可以快速计算J(n)了。但是我们还是不满足,递归式算起来还是太麻烦,有没有更好的方法呢?

    我们在观察上面的表,有没有发现什么呢?

    1,1,3,1,3,5,7,1,3...

    1,1,3,1,3,5,7,1,3,5,7,9,11,13,15,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,1!

    好像。。按2的幂次分组,然后每一个都是前一个加二!

    [J(n)=2l+1 , n=2^m+l , lin[0,2^m) ]

    可以归纳一下:

    首先,1很明显符合该性质。

    现在假设前i-1符合这个性质,那么

    如果i为偶数,则:

    [J(n)=2J(frac{n}{2})-1=2(2frac{l}{2}+1)-1=2l+1 , n=2^m+l , lin[0,2^m) ]

    如果i为奇数,则:

    [J(n)=2J(frac{n-1}{2})+1=2(2frac{l-1}{2}+1)+1=2l+1 , n=2^m+l , lin[0,2^m) ]

    证毕。

    还有什么性质吗?

    不妨从二进制的眼光来看一看这个问题:

    (n=(1b_{m-1}cdots b_1b_0)_2)

    (2^m=(10cdots 00)_2)

    (l=(0b_{m-1}cdots b_1b_0)_2)

    (J(n)=2l+1=(b_{m-1}cdots b_1b_01)_2)

    J(n)是n循环左移了一位!


    约瑟夫问题讲完了,还有吗?

    当然还有了,你没看见题目吗?

    一类特殊的递归式

    虽然我们成功的解决了约瑟夫问题的一种简单形式,并能够在(O(1))(m确定)或(O(loglogn))(m不确定)的时间复杂度内解决,但是我们还远远没有满足。不妨再来看看这个递归式:

    [J(1)=1 ]

    [J(2*n)=2J(n)-1 ]

    [J(2*n+1)=2J(n)+1 ]

    太特殊了,我们来看看这个:

    [f(1)=alpha ]

    [f(2*n)=2f(n)+eta ]

    [f(2*n+1)=2f(n)+gamma ]

    容易看出,前面的就是(alpha =1,eta =-1 ,gamma =1)的特殊情况。怎么办?

    当然还是打表了。

    n f(n)
    1 (alpha)
    2 (2alpha + eta)
    3 (2alpha + gamma)
    4 (4alpha + 3eta)
    5 (4alpha+2eta+gamma)
    6 (4alpha+ eta+2gamma)
    7 (4alpha +3gamma)
    8 (8alpha+7eta)
    9 (8alpha+6eta+gamma)
    (cdots) (cdots)

    有了上面的经验,这次就简单一点了。

    首先按二的幂次分组,然后大力猜结论。

    我们设(f(n)=A(n)alpha+B(n)eta+C(n)gamma),剩下的就是求出来(A(n),B(n),C(n))

    当然,我们还是可以归纳,但是在这里,我们可以用一些更简单的方法:

    我们令(alpha =1,eta=0,gamma=0),那么原递归式就变成了

    [f(1)=1 ]

    [f(2*n)=2f(n) ]

    [f(2*n+1)=2f(n) ]

    易知,(f(n)=2^m ,n=2^m+l,lin[0,2^m))

    (f(n)=A(n))

    所以(A(n)=2^m)

    然后我们令(f(n)=1)

    [1=alpha ]

    [1=2*1+eta ]

    [1=2*1+gamma ]

    解得(alpha=1,eta=-1,gamma=-1)

    所以(f(n)=A(n)-B(n)-C(n)=1)

    (f(n)=n)

    [1=alpha ]

    [2n=2n+eta ]

    [2n+1=2n+gamma ]

    解得(alpha=1,eta=0,gamma=1)

    于是得到方程:(A(n)+C(n)=n)

    所以:

    [left { egin{array}\ A(n)&=2^m\ A(n)-B(n)-C(n)&=1\ A(n)+C(n)&=n end{array} ight . ]

    解得:

    [A(n)=2^m,B(n)=2^m-l-1,C(n)=l ]

    小总结:解递归式时可以带入几个比较特殊的数或者是函数,来帮助我们计算,可以减少我们找规律然后再归纳的时间。

    这样就行了?

    当然不行。

    上面我们找到了关于2进制的性质,那么现在有没有呢?

    当然有了,为什么没有呢。

    我们设(eta_0=eta,eta_1=gamma),带到原递归式里看一看吧。。

    [egin{array}\ f((b_mb_{m-1}cdots b_1b_0)_2)&=2f((b_mb_{m-1}cdots b_1)_2)+eta_{b_0}\ &=4f((b_mb_{m-1}cdots b_2)_2)+2eta_{b_1}+eta_{b_0}\ &=cdots\ &=2^malpha+2^{m-1}eta_{b_{m-1}}+cdots+2eta_{b_1}+eta_{b_0} end{array} ]

    如果2进制位里面不止可以填01的话,那就相当于:

    [f((b_mb_{m-1}cdots b_1b_0)_2)=(alphaeta_{b_{m-1}}cdotseta_{b_1}eta_{b_0})_2 ]

    这样还不够,这并不是我们的一类递归式。真正的递归式在下面:

    [f(i)=alpha_i ,iin[1,c) ]

    [f(cn+i)=df(n)+eta_i,iin[1,c) ]

    这个跟上面的是差不多的。直接扔结论:

    [f((b_mb_{m-1}cdots b_1b_0)_c)=(alpha_{b_m}eta_{b_{m-1}}cdotseta_{b_1}eta_{b_0})_d ]

    现在差不多了。我才不会告诉你我就会这些。

    例题:有递归式:

    [egin{array}\ f(1)&=34\ f(2)&=5\ f(3n)&=10f(n)+76,\ f(3n+1)&=10f(n)-2\ f(3n+2)&=10f(n)+8\ end{array} ]

    求f(17)

  • 相关阅读:
    Android Gradle Plugin指南(五)——Build Variants(构建变种版本号)
    文件内容操作篇clearerr fclose fdopen feof fflush fgetc fgets fileno fopen fputc fputs fread freopen fseek ftell fwrite getc getchar gets
    文件操作篇 close creat dup dup2 fcntl flock fsync lseek mkstemp open read sync write
    嵌入式linux应用程序调试方法
    version control system:git/hg/subversion/cvs/clearcase/vss。software configruation management。代码集成CI:Cruisecontrol/hudson/buildbot
    最值得你所关注的10个C语言开源项目
    如何记录linux终端下的操作日志
    CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
    sizeof, strlen区别
    C/C++嵌入式开发面试题
  • 原文地址:https://www.cnblogs.com/shanxieng/p/10044861.html
Copyright © 2011-2022 走看看