描述
n个人围成一圈,编号分别为从1到n.从第1个人开始报数,数到2的人出列,再由下一个人重新从1开始报数,数到2的人再出列,……依次类推,直到只剩下一个人.请输最后一个人的编号.
(n<=100000)
输入
一个整数n
输出
若有解,则输出最后一个人的编码f(n)
若无解,则输出"No Solution."
输入样例 1
3
输出样例 1
3
这道题看起来很简单,但是n的大小让人汗颜,可能用循环链表都会超时。
那用队列怎么样?
用队列做约瑟夫问题是我上厕所的时候想到的(不要问我为什么qwq),先上代码:
#include<iostream>
#include<queue>
using namespace std;
int main()
{
queue<long long> p;
long long n,i,js;
cin>>n;
if(n<=0)cout<<"No Solution.";
else
{
for(i=1;i<=n;i++)p.push(i);
for(js=0;js!=n-1;js++)
{
p.push(p.front());
p.pop();
p.pop();
}
cout<<p.back();
}
return 0;
}
比循环链表还要短,而且效率非常高!(虽然递推式出来两个都得趴下)
思路:先将一到n填入队列,然后把队头加到队尾(还在圈内),删除队头,再删除一次队头(表示下一个出圈),这样循环n-1次,最后留下的就是答案。
效率高是因为它没有使用除for以外的任何判断,这是链表也不具有的速度。唯一的缺点就是:它很烧空间qwq,n再大一点会炸掉(我也没办法)。
关于约瑟夫问题如果有更高效的做法,欢迎留言!