约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。
那么第一个死的是(m-1)%n号,现在只剩下来n-1人,从m%n开始报数。
设f(n)表示共有n个人时最终存活的人,共10人,编号0-9,每次杀3号:
f(1)=0;只剩1个人,它的位置是pos=0;
f(2)=(0+3)%2=1;这个人在上一轮也存活,它的位置是:pos=(0+m)%2;
f(3)=(1+3)%3=1这个人在上上一轮也存活,它的位置是:pos=((0+m)%2+m)%3;
我们可以看出,最后一个杀死的人,在前一轮的排序正好与 这一轮的排序相差m,因为倒数第二轮从他开始,数了m个数后正好到他。f[1]=(f[0]+3)%2=1;
以此类推,他在倒数第三轮的排序正好与倒数第二轮相差m。
得到递推公式: f[i]=(f[i-1]+m)%i
因此,可以得到:
int lastRemaining(int n, int m) {
int f[n+1];
f[1]=0;
for(int i=2;i<=n;i++)
{
f[i]=(f[i-1]+m)%i;
}
return f[n];
}
进一步简化:
int lastRemaining(int n, int m) {
int res=0;
for(int i=2;i<=n;i++)
{
res=(res+m)%i;
}
return res;
}
网友评论