| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1166 人关注过本帖
标题:请教HJin的约瑟夫环求解函数
只看楼主 加入收藏
terisevend
Rank: 1
等 级:新手上路
帖 子:62
专家分:0
注 册:2007-6-2
收藏
 问题点数:0 回复次数:2 
请教HJin的约瑟夫环求解函数


可否解释一下nth_victim? 我知道是其中涉及数学...请大家用数学解释一下...谢谢了...

/*---------------------------------------------------------------------------
File name: Josephus_nth_victim.cpp
Author: HJin (email: fish_sea_bird [at] yahoo [dot] com )
Created on: 8/11/2007 20:23:48
Environment: Windows XP Professional SP2 English +
Visual Studio 2005 v8.0.50727.762


Modification history:
===========================================================================

Sample output

12 4 2
5 9 1 6 11 4 12 8 7 10 3 2

41 3 1
3 6 9 12 15 18 21 24 27 30 33 36 39 1 5 10 14 19 23 28 32 37 41 7 13 20 26 34 40
8 17 29 38 11 25 2 22 4 35 16 31

*/

#include <iostream>

using namespace std;

/** nth_victim of the Josephus circle.
* @param n --- number of people
* @param m --- step number
* @param s --- start
* @param k --- kth victim
* @return returns the original index of the kth victim.
*/
int nth_victim(int n, int m, int s, int k)
{
int p=k*m;
while(p>n)
p=(m*(p-n)-1)/(m-1);

p=(p+s-1)%n;
if(p==0)
p=n;

return p;
}


int main()
{
int n, m, s, k;
while(cin>>n>>m>>s)
{
for(k=1; k<=n; ++k)
cout<<nth_victim(n, m, s, k)<< " ";
cout<<endl<<endl;
}

return 0;
}

搜索更多相关主题的帖子: 约瑟夫 HJin 数学 函数 victim 
2007-08-13 21:53
neverDie
Rank: 1
等 级:新手上路
威 望:1
帖 子:123
专家分:0
注 册:2007-5-5
收藏
得分:0 
结果正确,过程不明。

数学啊~~~~~~~~

2007-08-14 12:12
terisevend
Rank: 1
等 级:新手上路
帖 子:62
专家分:0
注 册:2007-6-2
收藏
得分:0 

从网上找来了说明...不过有些地方不太懂...红色字部分就是...请大家帮帮忙...赐教赐教...小弟愚笨...

[QUOTE]

无论是用链表实现还是用数组实现都有一个共同点:要模拟整个游戏过程,不仅程序写起

比较烦,而且时间复杂度高达O(nm),当n,m非常大(例如上百万,上千万)的时候,几乎是
没有办法在短时间内出结果的。我们注意到原问题仅仅是要求出最后的胜利者的序号,而

是要读者模拟整个过程。因此如果要追求效率,就要打破常规,实施一点数学策略。

为了讨论方便,先把问题稍微改变一下,并不影响原意:

问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开

报数。求胜利者的编号。

我们知道第一个人(编号一定是m%n-1) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环
(以编号为k=m%n的人开始):
k k+1 k+2 ... n-2, n-1, 0, 1, 2, ... k-2
并且从k开始报0。

现在我们把他们的编号做一下转换:
k --> 0
k+1 --> 1
k+2 --> 2
...
...
k-2 --> n-2
k-1 --> n-1

变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x

最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗?!!变

去的公式很简单,相信大家都可以推出来:x'=(x+k)%n

如何知道(n-1)个人报数的问题的解?对,只要知道(n-2)个人的解就行了。(n-2)个人的解
呢?当然是先求(n-3)的情况 ---- 这显然就是一个倒推问题!好了,思路出来了,下面写
递推公式:

令f[i]表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n]

递推公式
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1)

有了这个公式,我们要做的就是从1-n顺序算出f[i]的数值,最后结果是f[n]。因为实际生
活中编号总是从1开始,我们输出f[n]+1

由于是逐级递推,不需要保存每个f[i],程序也是异常简单:
#i nclude <stdio.h>

main()
{
int n, m, i, s=0;
printf ("N M = "); scanf("%d%d", &n, &m);
for (i=2; i<=n; i++) s=(s+m)%i;
printf ("The winner is %d\n", s+1);
}

这个算法的时间复杂度为O(n),相对于模拟算法已经有了很大的提高。算n,m等于一百万

一千万的情况不是问题了。可见,适当地运用数学策略,不仅可以让编程变得简单,而且

往会成倍地提高算法执行效率。
[/QUOTE]

例如x

最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗?!!变

去的公式很简单,相信大家都可以推出来:x'=(x+k)%n



把X变回去是什么意思?变回什么? x'=(x+k)%n 又是如何推出来的...

2007-08-16 20:03
快速回复:请教HJin的约瑟夫环求解函数
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.016172 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved