经典问题之约瑟夫问题的快速解决
来源:互联网 发布:cntk caffe 编辑:程序博客网 时间:2024/05/06 13:24
此问题非常经典,在网上即可找到原题,在此不做描述。
对于原问题模型,一有链表法解决问题,效率极低,在此描述一种用树状数组完成问题的超快速做法。
首先,我们可以有这样递推的思路:不断加k模n,并减去其数字前走了的人即为当前人的真实编号(即是这一轮应踢走的人的编号),如何快速维护每个人其前走了的人的和,答案为树状数组。
现在模拟一下过程,假设有6个人,k=3(每报3个,走一个人)。
初始状态:1 2 3 4 5 6
用树状数组在每个人的位置加一,可得前缀和:1 2 3 4 5 6
现在1+2(其实是k-1)=3走了:1 2 4 5 6
用树状数组在3的位置减1,可得前缀和:1 2 2 3 4 5
再走了3+2=5,5%(6-1)=5(走了一个人,故6需减1)等等,此时并不是走了5,而是在树状数组中前缀和为5的数字,由上可知走了6:1 2 4 5
用树状数组在6的位置减1,可得前缀和:1 2 2 3 4 4
又按5+2=7,7%(6-2)=3,但这时在树状数组的前缀和中查找3,可见是第四个人的状态为3,故此回合走了4:1 2 5
用树状数组在4的位置减1,可得前缀和:1 2 2 2 3 3
又按3+2=5,5%(6-3)=2,在树状数组中查找二,可见即为2,
故此回合走了2:1 5,
前缀和改为:1 1 1 1 2 2
最后2+2=4,4%(6-4)=2,在树状数组中查找2,可见为5,
故最后只剩1了。
因为前缀和是单调的,所以查找可以用二分。
可得序列为:3 6 4 2 5 1
//不信的话可以和链表验证一下。
参考程序:
#include<cstdio>#include<algorithm>#include<cstring>#include<ctime>#define maxn 1000000using namespace std;int bit[maxn];int n,k;int sum(int i){int s=0;while (i>0){s+=bit[i];i-=(i&-i);}return s;}void add(int i,int x){while (i<=n){bit[i]+=x;i+=(i&-i);}}int binary_search(int id){int l=0,r=n;while (l<r){int mid=(l+r)>>1;if (sum(mid)<id)l=mid+1;else r=mid;}return l;}int main(){freopen("input.in","r",stdin);freopen("output.out","w",stdout);while (scanf("%d%d",&n,&k)==2){int id=1;memset(bit,0,sizeof(bit));for (int i=1;i<=n;i++)add(i,1);for (int i=1;i<=n;i++){id=(id+k-2)%(n-i+1)+1;int newid=binary_search(id);printf("%d ",id);add(newid,-1);}}printf("\nUsed Time=%.2f",(double)clock()/CLOCKS_PER_SEC);return 0;}
为什么说这种方法快呢?
1.检验:在n=100000的情况下,仅费时0.24秒。
2.可以明显得O(n*(logn)^2),应该算是很快了。
对于只需要最后幸存者的问题,可参见递推解决
- 经典问题之约瑟夫问题的快速解决
- 经典算法之约瑟夫问题
- 约瑟夫问题的解决
- 经典算法问题之约瑟夫问题
- 【经典问题】约瑟夫问题
- 约瑟夫环问题的解决
- 经典算法之约瑟夫环问题
- 经典约瑟夫环问题
- 约瑟夫问题(经典问题)
- 小猪的数据结构辅助教程——2.5 经典例子:约瑟夫问题的解决
- java 解决约瑟夫问题
- 约瑟夫问题Java解决
- 解决约瑟夫问题
- php解决约瑟夫问题
- JAVA解决约瑟夫问题
- 快速解决工作中遇到经典的括号匹配问题
- PHP解决约瑟夫环的问题
- C/C++之单链表(含约瑟夫问题)经典总结
- 关于AndroidStudio中提示cannot resolve symble R,但程序可以正常build和run的问题
- Java反射详解
- 最小生成树 [克鲁斯卡尔算法] --->图
- 计算机图形学(二)
- sqlserver 中NOLOCK、HOLDLOCK、UPDLOCK、TABLOCK、TABLOCKX
- 经典问题之约瑟夫问题的快速解决
- error: insufficient permissions for device(解决adb shell问题)
- JavaEE学习笔记之SSH—Hibernate(2)
- Ubuntu14.04下eclipse中使用rohc库
- Java创建线程的两个方法
- Poj 3304 Segments
- 好的技术网站总站总结
- Xcode及常用插件安装
- 分析能力提高篇三:不懂装懂、无知者无畏的指手画脚,是大学正常发展的极大障碍