洛谷P2696之慈善的约瑟夫——题解

洛谷P2696题解

[传送锚点](P2696 慈善的约瑟夫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))
比不过大佬,从蒟蒻做起
选择比较有意思的解法——用队列模拟(还是窝太弱了)


正片开始

考虑队列模拟,因为每次都是假的剔除,所以我们的目标是找到每回游戏的最终存活者。
将不被剔除,即每次编号求余2结果为1的人再次扔进队列里,直到队列长度为一,最后剩下的就是最终幸存者。

ll del(ll x)
{
	for(int i=1;i<=x;i++) q.push(i);
	int f=1;
	while(q.size()!=1)
	{
		int u=q.front();q.pop();
		if(f%2==1) q.push(u),f++;
		else f++;
	}
	int ans=q.front();
	q.pop();
	return ans;
}

接下来就可以开始快乐的处理答案了。
直接干while循环,直到最终幸存者(记为s)是序列的最后一人,对于每次剔除的人n-s,将ans+=n-s。结束循环前,将最后剩余的s人乘上2加到ans里即可。


完整代码

#include <bits/stdc++.h>
using namespace std; 
typedef long long ll;
queue<int>q;
ll del(ll x)
{
	for(int i=1;i<=x;i++) q.push(i);
	int f=1;
	while(q.size()!=1)
	{
		int u=q.front();q.pop();
		if(f%2==1) q.push(u),f++;
		else f++;
	}
	int ans=q.front();
	q.pop();
	return ans;
}
int n,ans;
int main() 
{
	cin>>n;
	while(1)
	{
		int s=del(n);
		if(s==n) 
		{
			ans+=2*s;
			break;
		}
		ans+=n-s;
		n=s;
	}
	cout<<ans<<endl;
	return 0;
} 


本蒟蒻实力有限,如有错误还请各位大佬指出。
谢谢

posted @ 2024-08-01 11:49  Nightmares_oi  阅读(16)  评论(0编辑  收藏  举报