题目描述:
N个人(编号1-N),站成一排,进行报数游戏。报数过程可能进行很多轮,有如下规则:
(1) 如果剩余人数不超过3个人,则游戏结束。
(2) 大家报数,然后留下报奇数的人继续游戏,或者留下报偶数的人继续游戏。
重复如此(1)(2)两步骤,到游戏结束。
问:最终剩下的三人组有多少种情况?(注意是三人组,例如如果最后剩下2个或者1个人,不计入结果中)。
输入n, (0<n<=10000000)
输出最终结果。
解法:
这道题同样是约瑟夫斯问题,这道题目的意思是,通过k次消去操作(消去奇(或偶)数位的人),使得剩余人数小于等于3,如果人数为3,统计这样的3人组的数量。首先需要说明一条结论:把k次消去操作看作一个过程,那么如果过程1和过程2的第i次消去操作是第一次不同的消去操作,1<=i<=min(k1,k2),,(比如过程1的第i次消去奇数位的人,过程2的第i次消去偶数位的人)那么无论后面过程1和过程2如何进行消去操作,过程1剩下的人与过程2剩下的人都不会相同。因为第i次消去操作后,过程1与过程2剩下的人所在的(奇、偶)域已经不相同。可以从下图理解:
既然不同的消去操作剩下人所在域不一样,我们就可以只关心消去操作后剩下的人数,这样我们就可以通过如下递归消去奇(或偶)数位的人方法来统计三人组的情况:
int count(int n){
int res=0;
if(3==n){
res=1;
}else if(n<=2){
}else
res=count(消去偶数位后剩余人数)+count(消去偶数位后剩余人数);
return res;
}
递归深度为depth=log(n),复杂度为O(2^depth)=O(n)。
代码见:http://blog.youkuaiyun.com/xhu_eternalcc/article/details/18178941