约瑟夫问题及其变形

部分转自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;
}

(留坑)

时间: 2024-08-11 01:21:34

约瑟夫问题及其变形的相关文章

约瑟夫环的变形

问题描述: 输入一个由随机数组成的数列(数列中每个数均是大于0的整数,长度已知),和初始计数值m.从数列首位置开始计数,计数到m后,将数列该位置数值替换计数值m,并将数列该位置数值出列,然后从下一位置从新开始计数,直到数列所有数值出列为止.如果计数到达数列尾段,则返回数列首位置继续计数.请编程实现上述计数过程,同时输出数值出列的顺序. 比如:输入的随机数列为:3,1,2,4,初始计数值m=7,从数列首位置开始计数(数值3所在位置) 第一轮计数出列数字为2,计数值更新m=2,出列后数列为3,1,4

UVa 1394 约瑟夫问题的变形

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4140 本来是要昨天来写这学习代码的,然后昨晚寝室又断电了,忍不住在这里吐槽一下,嗯,寝室天天断电. 题意就是输入n,k,m三个数,n个数排成一个圈,第一次删除m,以后每数k个数删除一次,求最后一个被删除的数. 言归正传,以前写过一个链表的约瑟夫问题,但是在这里肯定是会超时的.后来看了些参考

UVALive 3882--And Then There Was One+约瑟夫环问题变形

题目链接:点击进入 题目意思大概和约瑟夫环问题差不多,唯一的不同点在于起点改成了m:刚开始的时候我想直接链表模拟算了,但是后面一看,数据太大,就改用公式做了.约瑟夫环的公式是:f(n)=(f(n-1)+k)%n ,对于这个题起点为m,所以答案就会变成ans=(f(n)+m-k+1)%n; ans有可能小于0,此时我们要给他加上一个n,ans+=n. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #

例26 约瑟夫问题的变形(And Then There Was One,Japan 2007,LA 3882)

题目描述           n个数排成一个圈.第一次删除m,以后每k个数删除一次,求最后一个被删除的数. 题目分析            首先为了取模,n个人编号为0,1,2......n-1,当只有1个人时,肯定是编号为0的(只有它),所以dp[1]=0,        当有两个人时,最后剩下的(dp[1]+k)%2,就是反向思考的过程,于是dp[i]=(dp[i-1]+k)%i;               还有就是由于第一次是删除的m,那么还要将这个差值补上,于是ans=(dp[n]+k

poj 2886 Who Gets the Most Candies?(线段树+约瑟夫环+反素数)

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 9934   Accepted: 3050 Case Time Limit: 2000MS Description N children are sitting in a circle to play a game. The children are numbered from 1 to N in clockwise o

poj 1012 Joseph (约瑟夫问题)

Joseph Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 47657   Accepted: 17949 Description The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n,

小白书关于动态规划

10192 最长公共子序列 http://uva.onlinejudge.org/index.php?option=com_onlinejudge& Itemid=8&page=show_problem&category=114&problem=1133&mosmsg= Submission+received+with+ID+13297616 */ #include <cstdio> #include <string.h> #include&

【hoj】1016 Joseph&#39;s problem I

约瑟夫问题是一个很经典的问题,描述的是n的人围成一圈,每次数到第m个人就会被淘汰,之后在淘汰的人开始在数起第m个人,这样下去只带还剩下1个人为胜利者,这个题是约瑟夫问题的变形,它每次裁定的标准不再是一个恒定的m而是按照素数表中的第i次淘汰第i个人,所以我们需要求出素数表才能知道裁定的次序,也才能求出剩下的人的序号 首先,对于约瑟夫原本的问题是可以对每次淘汰使用逐个列举,将这n个人每个人都列举,没有出局的话就计1直到数到还没淘汰的第m个,但是这样下来对于n值很大的情况就会很耗时间,所以一定会有别的

POJ 1012 Joseph(打表题)

题意:约瑟夫环的变形.要求寻找到一个杀人循环节m使后半节的坏人先被所有杀光. 直接链表模拟出结果,再打表即可: 代码:(凝视的是打表码) #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<queue> #include<string> #include<cstring> #include<algorithm> u