节目主持人准备从n名学生中挑选一名幸运观众,因为大家都想争当幸运观众,老师只好采取这样的办法:全体同学排成一列,由前面往后面依顺序报数1,2,1,2,……,报单数的同学退出队伍,余下的同学向前靠拢后再重新由前往后1,2,1,2,……报数,报单数者退出队伍,如此下去最后剩下一人为幸运观众。编程找出幸运观众在原队列中站在什么位置上?
题目描述
节目主持人准备从n名学生中挑选一名幸运观众,因为大家都想争当幸运观众,老师只好采取这样的办法:全体同学排成一列,由前面往后面依顺序报数1,2,1,2,……,报单数的同学退出队伍,余下的同学向前靠拢后再重新由前往后1,2,1,2,……报数,报单数者退出队伍,如此下去最后剩下一人为幸运观众。编程找出幸运观众在原队列中站在什么位置上?
输入
仅一个整数n(n≤10000)。
输出
仅一个整数,表示幸运观众在原队列中站的位置。
样例输入
5
样例输出
4
(时间限制: 1 Sec 内存限制: 128 MB)
请大佬给出题目的思路,最好能给出主要代码,谢谢!
你等我,我来!
这个其实很简单,是一道规律题,找规律就能发现,其实这个题目的答案就是小于n的最大的2^m的数字。
我们可以先一段暴力的程序,(当然这个规律我在纸上找到的)
#include <iostream> #include <stdio.h> #include <string.h> #include <string> using namespace std; int n; int a[10005]; int main() { scanf("%d",&n); for(int i=0;i<n;i++) { a[i]=(i&1?0:1); } int ans=0; while(true) { int x=1; int tag=0; for(int i=0;i<n;i++) { if(a[i]==0) { if(x==1) {a[i]=1;x=0;} else x=1; tag++; ans=i; } } if(tag==1) break; } printf("%d",ans+1); return 0; }
这个程序显然是超时的,但是我们输入数据发现
8 --- 8
17 --- 16
5 ---- 4
267 --- 256
129 --- 128
130 --- 128
验证了上面的规律,所以正真的解题程序如下:
#include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <math.h> using namespace std; int n; int a[10005]; int main() { scanf("%d",&n); int ans=0; for(int i=1;i<16;i++) { int x =(int)pow(2.0,i); if(x>n) {ans=i; break;} } printf("%d",(int)pow(2.0,ans-1)); }
这类规律题,一般在纸上就能把规律找出来。
谢谢您!虽然我昨天晚上就想出来了,但是还是表示感谢!附上我的代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxN=10001; int n; bool flag[maxN]; int main() { memset(flag, true, sizeof(flag)); scanf("%d", &n); int sum=0, t=1, k=2; for(int i=1; i<=n; i++) if(i&1) { flag[i]=false; sum++; } while(sum<n-1) { for(int i=t*2; i<=n; i+=k*2) //if((i+k*2)>n) break; //else { if(i<=n) { flag[i]=false; sum++; if(sum==n-1) break; } else break; //} t*=2, k*=2; } for(int i=1; i<=n; i++) if(flag[i]) printf("%d", i); return 0; }
@Antinue: 我的代码提交是AC的吗
想到了约瑟夫环。可以参考一下约瑟夫环算法。