void-man

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

求解约瑟夫问题,J(n)表示n个人第二个给踢掉的与瑟夫问题的解,然后要求求解m次此嵌套函数

在网上搜到了两种办法,第一种直接通过递归求解约瑟夫的解

讨论如下,假设原先有2n个人。那么,在绕第一圈之后,留下:
[attach]76340[/attach]
此时剩下n个人,分别为 第一个人12×11),第二个人32×21)。。。第n个人2n12n1),假设知道此时(n个人)将得到的幸存者为x,那么有:第x个(2x1),明显的,n个人里的第x个也就是之前在2n个人的时候的第2x-1个,此时可以建立起从J(2n)J(n)的关系:J(2n) = 2 * J(n)-1,n1
同理,我们可以找到奇数时的关系:J(2n+1) = 2 * J(n)+1, n1
由上,有递推公式:
J(1)=1;
J(2n) = 2 * J(n)-1,n1
J(2n+1) = 2 * J(n)+1, n1
到这里,我们已经找出了一个可以解决问题的递推公式了,可以根据这个公式编程求解。

 

For example:

long Josephus(long n){

if (n==1)return 1;

else if (n%2) return 2*Josephus(n/2)+1;

else return 2*Josephus(n/2)-1;

return -1;

}

 还有一个算法,不是太明白,先把代码放上过几天理解了再说

1 #include<iostream>
2  using namespace std;
3 long long aa[64];
4 long long power(long long n)//计算2的N次方的函数
5 {
6 long long t;
7 if(n==0) return 1;
8 if(n==1) return 2;
9 if(n%2==0) return (t=power(n/2))*t;
10 if(n%2==1) return (t=power((n-1)/2))*t*2;
11 }
12 int main()
13 {
14 long long a,i,n,pre;
15
16 for(i = 0;i<=62;i++)
17 aa[i] = power(i);
18 while(cin>>a>>n)
19 {
20 while(n--)
21 {
22 pre = a;
23 for(i = 0;i <= 61;i++)
24 if(a>=aa[i] && a<aa[i+1])
25 break;
26 if(a >= aa[62] ) i=62;
27 a = (a-aa[i])*2+1;
28 if(a==pre) break;
29 }
30 cout << a << endl;
31
32 }
33 return 0;
34 }
posted on 2011-04-16 22:07  void-man  阅读(293)  评论(0)    收藏  举报