/*
第二种方法其实是一种递归的方式,它是将递归的结果进行逆推的
第一步:
约瑟夫环最后一次的执行其实就是两个人之间进行
将此时的二人进行编号为0,1,从0开始报数,我们很容易想到需要的值m:
如果是奇数的话,最后一个报数的是0,胜利者是1
如果是偶数的话,最后一个报数的是1,胜利者是0
公式实现:f(2, m) =(0 + m)% 2这样可以的到获胜者的下标
第二步:
倒数第二次是3个人进行
将此时的三人编号为0,1,2,从0开始报数,我们可以了解到时先淘汰了一人,然后是两个人进行的比赛
此时淘汰的下标识m%3,还剩下两个,我们可以就回到最初的两个人的比较,只是,我们第一步中是重新编了号的,
我们需要知道新编号对应的第二步中的编号是什么?
我们可以知道我们在编辑新的编号是从0开始的,但是和旧编号还是有一一对应的关系的
新编号 = (旧编号 - m)% 现在的人数(即未开始执行的人数,在这一步就是3)
这里会有负数的取模,这样会从被淘汰的下一位从0开始,被淘汰的前一位会是最大的数(可以自己去了解一下计算机对于负数是怎样取模的)
旧编号 = (新编号 + m)%现在的人数
可以得到公式:f(3,m) = (f(2, m) + m) % 3
依次递归下去:f(n,m) = (f(n - 1, m) + m) % n
所以第二种方式实际上是有上面的递归式倒着来的
从两个人开始,下标也是从0开始变化(1个人就是0结束嘛) ,一直到n个人
*/
#include <stdio.h>
int main()
{
int n, m;
scanf("%d %d", &n, &m);
int s = 0;
for(int i = 2; i <= n; i++)
{
s = (s + m) % 2;
}
// 我们的下标是从0开始的,最终人的序号是从1开始的所以结果加一,也可以最开始的时候就是s=1
printf("%d", s + 1);
return 0;
}
约瑟夫环递归方式
最新推荐文章于 2022-03-01 16:29:20 发布