一道经典题目

时间:2021-07-26 14:21:52

题目:有10个人围成一圈,从1到3循环报数,数到3的人退出,最后剩下的人是谁?

这道题,可以抽象成这样:有N个人围成一圈,从1到M报数,数到M的人退出,最后剩下的人是谁?

 

以前在写程序解这道题的时候都是用数组+for循环的方式实现。今天偶然见到一种牛逼方法:一个公式F(N) = (F(N-1)+M)%N;

此公式的推导过程如下:

1:假设有N个人 1 2 3 ..... N  数到M的出列
2:第一次第(M)个人  出列    也就是  1  2 M-1 ?  M+1  ...N
3:这里有个问题 如果M大于N的话怎么办?

    3.1:如果M小于N  那么出列的就是M  
    3.2:如果 M > N  那么就是M除以N的余数:例如 2 个人数到 3  第一个出列的就是 3%2 = 1;
    3.3:针对第一种情况 M<N.  M%N=M  所以 第一个出列的人就是M%N.  则 F(1) = M % 1 = 0。 
 
 4:第二次出列的人就是第一个出列的人再往后数M个人,也就是第2M个人出列  也就是 F(N-1) + M
 5:这时就有个问题第一次出列的问题  
 6:所以第二次出列的就是 2M % N.  也就是  F(N) = (F(N-1)+M)%N

 

所以程序代码如下:

public static int jie(int n, int m) {
if (n == 1) return 0;
else return ((jie(n - 1, m) + m) % n) ;
}


擦。两行代码就实现了。

数学太强大!!!!!!!!!!!!!!