joseph环(PKU1012题)哪位高手帮忙提供个简洁的算法

joseph环(PKU1012题)谁帮忙提供个简洁的算法啊
1012我用了循环链表太慢,超时,换成用变长数组还是太慢,后来听说这是个数学问题,数学上有公式的?!!哪个大狭晓得啊?请回帖告知~   小弟谢过~~

------解决方案--------------------
有一个公式:J(2^m+t) = 2t+1


其中m是不小于要计算数的最大的2次幂,例如10 = 2^3 + 2, 100 = 2 ^6 + 36

上面的2和36就相当于上面公式的t。


------解决方案--------------------
hailongchang给的公式出自《具体数学》,楼主想了解的话,可以从网上下来看。

不过,这个公式用在这个题上,其实并不合适。

给楼主一个链接,希望有帮助。

http://www.it130.cn/Article/FAQ/bianchengyuyan/suanfa/2007-3-7/2007030717261410.html

------解决方案--------------------
记得我贴过一次了,再贴吧。
其中打表可以在本机上完成,在程序中写
m[]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881}
就可以了。

/******************************************************************************
acm POJ 1012
Joseph
Central Europe 1995

milksea
Feb. 10, 2007
******************************************************************************/

#include <stdio.h>

enum {KSUP = 14};

int main()
{
void getlist(int m[]);
int k, m[KSUP];
getlist(m);
while (scanf( "%d ", &k) == 1 && k != 0)
printf( "%d\n ", m[k]);
return 0;
}

/* 打表 */
void getlist(int m[])
{
int k, mt;
for (k = 1; k < KSUP; ++k) {
for (mt = k + 1; /* null */; mt += k + 1) { /* 根据最后两步剪枝 */
if (valid(k, mt, 0, k)) {
m[k] = mt;
break;
}
else if (valid(k, mt + 1, 0, k)) {
m[k] = mt + 1;
break;
}
}
}
}

/* 递归判断m是否有效 */
int valid(int k, int m, int pos, int bad)
{
if (bad == 0) /* 坏人死绝了,OK */
return 1;
else if ((pos + m) % (k + bad) <= k && (pos + m) % (k + bad) != 0)
/* 好人将死,不行 */
return 0;
else /* 坏人该死,继续 */
return valid(k, m, (pos + m - 1) % (k + bad), bad - 1);
}