约瑟夫环解体报告

12.
【问题描述】要从n只猴子中选出一位大王。它们决定使用下面的方法:
n只猴子围成一圈,从1到n顺序编号。从第q只猴子开始,从1到m报数,凡报到m的猴子退出竞选,下一次又从退出的那只猴子的下一只开始从1到m报数,直至剩下的最后一只为大王。请问最后哪只猴子被选为大王。
【输入形式】控制台输入三个整数n,m,q。
【输出形式】输出最后选为大王的猴子编号。
【样例输入】
7  4  3
【样例输出】
4
【样例说明】输入整数n = 7,m = 4,q = 3,输出4




数学思想:
1----先假设从第一只猴子开始报数(就是不考虑q值的存在)
先让n = 7, m = 4,






正常的思考方式:


刚开始     [1,2,3,4,5,6,7]----共7个
第一次退出 [1,2,3,5,6,7]  ----共6个
第二次退出 [2,3,5,6,7]    ----共5个
第三次退出 [2,3,5,7]      ----共4个
第四次退出 [2,3,7]        ----共3个
第五次退出 [2,3]          ----共2个
第六次退出 [2]            ----共1个


运用数学的递归的思想转化为问题(每次都改变次序,使数组(这里不一定是数组,就是指的每次储存数据的[])的开头都为应报1的猴子):


刚开始     [1,2,3,4,5,6,7]----共7个
第一次退出 [5,6,7,1,2,3]  ----共6个
第二次退出 [2,3,5,6,7]    ----共5个
第三次退出 [7,2,3,5]      ----共4个
第四次退出 [7,2,3]        ----共3个
第五次退出 [2,3]          ----共2个
第六次退出 [2]            ----共1个


现在可以从上面的过程中提炼公式(也就是找规律)
可能你不一定可以直接的找出这个规律(我就是那个看不出来的人###)
那就先给出公式,然后在“缕缕”
倒着看,最后剩下的为2号(当然这是开始就排的序号)
从第六次看,索引为0值为2(值这里指的是编号,下面统称为值)
第五次,在其中找到值为2的,可得索引为0,
第四次,同上步可得索引为1
。。。。。。
然后经过推到就可以得到(注意new,old 这里指的索引)old = (new + m)%n(如果问为什么?这个我觉得对于我这种菜鸟,这需要先记着公式,会套用,难道你还指望在考场上退出来,那刷题岂不是变得没有意义)
这做一下简单的推导:最后一次的推出的索引一定为零(因为只剩下了一个元素)




最后添上q后也只是在上面推出到最后在从0的基础上进行前后的移动,若最后的得到的索引加上q超过数组的长度-1,又因为这是一个环形,所以可以减去一完整的环的长度,从而得到了题目的解
最后附上题解:
#include <iostream>
using namespace std;
int main()
{
    int n,m,q;
    // n = 7 m = 4
    cin >> n >> m >> q;
    int k = 0;
    for(int i = 2; i <= n; i++)
    {
        k = (k + m) % i;
    }
    if((k + q) > n )
    {
        cout << k + q - n;
    }
    else
    {
        cout << k + q;
    }
    return 0;
}
编程小白,有错多多包涵,有错误欢迎指出









猜你喜欢

转载自blog.csdn.net/qq_41682681/article/details/80678850