幸运人士
时间限制 : 1.000 sec 内存限制 : 128 MB
题目描述
一次大型派对的最后节目是选出一位幸运人士,该人士将获得派对组织者准备的一个钻石戒指。
而选择幸运人士的办法是让所有人员一字排列,然后从左至右点数,凡是奇数号的全部剔除。
对于剩下的人员,又从左至右点数,逢奇数号就剔除。
如此不断递归下去,直到只剩下一个人为止,此人即为幸运之人。
请设计一个递归算法计算幸运之人所在的位置。
输入
多组数据,每组输入一个正整数n。
输出
输出最后剩下的那个人的位置。
样例输入
1
2
3
样例输出
1
2
2
解题思路
看到题目其实第一反应是用vector开动态数组,但是要用递归的话就有些懵,不知道从何下手,想去找博客看看有没有思路解析,但是自己看不明白。。。所以就把链接放在这里,想看的自己直接看:(我们学校超级厉害的学长写的)
链接: 幸运人士(STL双vector使用).
我要讲的,是另外一种超级简单的解法,虽然也有博主直接放出来代码,但是没有详细介绍。。。所以我看到代码的时候真的一脸懵。。。没想到自己能找到规律写出来,就来讲一讲:
根据题目,我们可以作出下图:
我们仔细观察 n 和 m 的关系,可以尝试推出规律:
n 和 m 可以按照 每 2t(t=0;t++)个为一组 来分组,每一组的m都是上一组m的二倍,n的个数也是上一组的二倍;
所以我们的递归就可以反过来,令f(n)=m,
n的值是二倍二倍增长的,故前一次递归是f(n/2),m增长一倍,故m=f(n/2)*2。
递归的结束条件即,当n=1时,m=1。
关键公式就出来啦,现在再看代码应该就会很明白了:
#include <bits/stdc++.h>
using namespace std;
int f(int n){
if(n==1) return 1;//递归结束条件
else{
return f(n/2)*2;
}
}
int main(){
int n;
while(cin>>n){
cout<<f(n)<<endl;
}
return 0;
}
希望能对大家有帮助!!