约瑟夫问题及其变形
部分转自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; }
(留坑)