【acm结论】约瑟夫问题结论与数学分析

今天和大家分享一下约瑟夫问题的结论和数学推导。

对于传统的约瑟夫问题(例如猴子选大王问题),一般的解法就是直接模拟的方法,即数组下标法和循环链表法。能以以上两种方法做出约瑟夫问题的人,编程的功底都十分深厚。但是在正式的如蓝桥杯、acm尤其是在模拟赛等比赛中,此类问题均是作为妥妥的水题出现。而两种模拟法均会消耗大量的时间,是不讨好的行为。

但是如果我们在比赛中可以做到直接使用约瑟夫问题的结论来解决问题,那么我们的解题效率将会大大提升。话不多说,我们直接上核心代码

int main() 
{
	int n = 0;//n只猴子
	int m = 0;//报数m
	int s = 0;//每次出局的猴子编号
	cin >> n >> m;//scanf("%d %d",&n,&m);
	for (int i = 2; i <= n; i++) 
	{
		s = (s + m) % i;
	}
	printf("%d\n", s + 1);
}

(!!!注意这里是从第一个猴子开始报数的代码,从第k个猴子开始报数的代码略有不同。)

不要惊讶。没错,就是这么简单。你可能不知道这是为什么,那么我们接下来看一下自然语言解释下的约瑟夫问题的结论吧。

自然语言解释

当有n只猴子的时候,他们的编号依次是0、1、2、3、4、………、n-1。假设最后编号为y的猴子会留下来。

那么将该问题放在数学语言下为:

已知n和m,求解约瑟夫问题的函数(映射),那么代入数据,我们目标解(因变量)y就可以解出来了

那么该映射是什么样子的呢?

我们先来看第一轮报数。

因为数到m的那个猴子会出列(因为n可能小于m,所以上句话不是第m个猴子出列),那么此轮中编号为(m-1)%n的猴子会出列。

第二轮报数

编号为(m+0)%n的猴子将做为第二轮编号为0的人,此轮编号为(m+i)%n的人将做为下一轮编号为i的人,重复第一轮。

············

Y(1)= 0;

Y(2)= ( m + Y(1) ) % 2;

Y(3)= ( m + Y(2) ) % 3;

············

由数学归纳法得出第i轮(i<n)的映射:Y(i)=( m + Y(i-1) ) % i 

那么我们就可以得到这个每轮出圈猴子对应的映射(函数关系式):Y(i)=( m + Y(i-1) ) % i 

要知道Y(i),就必须知道Y(i-1)······而最后Y(1)=0;

因此,我们的整个核心代码就出来了,n-1重循环代表n-1轮,(也可以理解为n个猴子每次提一个,共踢了n-1个),循环体就是通过求模求解被踢的猴子。

故有

int main() 
{
	int n = 0;//n只猴子
	int m = 0;//报数m
	int s = 0;//每次出局的猴子编号
	cin >> n >> m;//scanf("%d %d",&n,&m);
	for (int i = 2; i <= n; i++) 
	{
		s = (s + m) % i;
	}
	printf("%d\n", s + 1);
}

怎么样你明白了么?

如果你觉得对你有帮助的话,请给作者一个赞吧QTQ。

我会把你的赞当作我前进的动力,继而不懈的继续前行!!!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星星也倦了/

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值