POJ 3517 约瑟夫问题

本文介绍了一个简洁的数学方法来解决约瑟夫环问题,通过递推公式f(n)=(f(n-1)+k)%n找到最后一个幸存者的编号,并提供了完整的C语言实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很早就看到过这个题目了,当时都是用循环链表做的,这样可以逐次节省内存。

没想到,这却可以用几行代码用数学方法轻松实现~


参考了学长Alex4814的博客,原来借助抽象函数f(n)可以解释得更清楚。

n个人编号:0,1,2,……,k-2,k-1,k,……,n-1;//包含0的话刚好是n的完全剩余系,更方便讨论

抽去第k人:0,1,2,……,k-2,k,……,n-1;//编号为k-1的是第k人

只剩下了n-1个人,相当于一个环减去了一节,重新安置头和尾:

  k,k+1,……,n-1,0,1,2,……,k-2;(x+k)%n

n-1个人编号:0,1,2,……,k-1,k,k+1,……,n-2;       x

于是问题化简到了n-1个人的求解问题。并且这两个数列除了k-1有一一对应的关系

设f(n)是n个人里幸存者的编号,那么:f(n)=(f(n-1)+k)%n

并且显然,有:f(1)=0

依次可以得到1,2,3,……,n人对应的幸存者编号;


题目给的编号是从1开始的,平移即可。


#include <stdio.h>
int main()
{
	int n, m, k;
	while(~scanf("%d%d%d", &n, &m, &k))
	{
		if(!n && !m && !k)
			break;
		int x = 0, y;
		for(int i = 2;i < n;i++)
			x = (m+x)%i;
		printf("%d\n", (x+k)%n+1);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值