约瑟夫问题及其变形

部分转自http://blog.csdn.net/kangroger/article/details/39254619,复习自用

本渣昨天晚上做了一道模拟赛,第一道题是一个递推的小题,上网一查原来这个题是有一个经典模型的

约瑟夫环问题:一圈共有N个人,开始报数,报到M的人自杀,然后重新开始报数,问最后自杀的人是谁?

 

如图:内环表示人排列的环,外环表示自杀顺序;上面N=41,M=3。

最普通办法就是模拟整个过程:建一个bool数组,true表示此人还活着,false表示已经自杀。可以模拟整个过程

可是模拟的速度太慢,是o(nm)的,时间上大概无法承受,我们考虑数学分析递推,考虑到没杀掉一个人,圈内的人数减一,一个求n人的过程变成了一个求n-1个人的过程,我们考虑从1开始递推

设f(n)为0~n-1个人中最后自杀的人是谁

①当n=1,这是一个平凡问题,一定是0号自杀

②假设f(n-1)已经求出来,我们考虑f(n)实际上是多了一个人,从1开始报数,这时m-1号自杀,再次报数,原来报1号的人由原来的0号变为了m号,2号变成了m+1号……,我们注意到实际上就是把编号往后推了M个,所以答案也要往后推M个,可以得到递推式子f(n) = f(n-1) + m mod n

#include<iostream>
using namespace std;
int main()
{
    int N;//人的总个数
    int M;//间隔多少个人

    cin>>N;
    cin>>M;
    int result=0;//N=1情况
    for (int i=2; i<=N; i++)
    {
        result=(result+M)%i;
    }
    cout<<"最后自杀的人是:"<<result+1<<endl;//result要加1
    return 0;
}

(留坑)

 
posted @ 2016-10-22 19:14  ACforever  阅读(716)  评论(0编辑  收藏  举报