约瑟夫问题
约瑟夫问题
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1073 范围:10^6
http://noi.openjudge.cn/ch0302/1748/ 范围:30
http://codevs.cn/problem/1282/ 范围:30000
-
以下四种方法时间复杂度递减
#include<cstdio> #include<cstring> using namespace std; int n,k; bool v[301]; int main() { while(scanf("%d%d",&n,&k)!=EOF) { if(!n) return 0; int now=-1,id=0,s=0; memset(v,0,sizeof(v)); while(s<n-1) { while(id<k) { now=(now+1)%n; if(!v[now]) id++; } v[now]=true; s++; id=0; } for(int i=0;i<n;i++) if(!v[i]) { printf("%d\n",i+1); break; } } }
蒟蒻的 #include<cstdio> #include<algorithm> #define N 1000001 using namespace std; int n,m; struct node { int l,r,sum; }tr[N*4]; void build(int k,int l,int r) { tr[k].l=l; tr[k].r=r; tr[k].sum=r-l+1; if(l==r) return; int mid=l+r>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); } int query2(int k,int opl,int opr) { if(opl==tr[k].l&&opr==tr[k].r) return tr[k].sum; int mid=tr[k].l+tr[k].r>>1; if(opr<=mid) return query2(k<<1,opl,opr); if(opl>mid) return query2(k<<1|1,opl,opr); return query2(k<<1,opl,mid)+query2(k<<1|1,mid+1,opr); } int query1(int k,int l,int s) { if(tr[k].l==tr[k].r) return tr[k].l; int mid=tr[k].l+tr[k].r>>1; int tmp=0; if(l<=mid) tmp=query2(k,l,mid); if(s<=tmp) query1(k<<1,l,s); else query1(k<<1|1,max(mid+1,l),s-tmp); } void change(int k,int w) { if(tr[k].l==tr[k].r) { tr[k].sum=0; return; } int mid=tr[k].l+tr[k].r>>1; if(w<=mid) change(k<<1,w); else change(k<<1|1,w); tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; } int query3(int k,int s) { if(tr[k].l==tr[k].r) return tr[k].l; int tmp=tr[k<<1].sum; if(s<=tmp) return query3(k<<1,s); return query3(k<<1|1,s-tmp); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(!n) return 0; build(1,1,n); int pos=0,k,tot,tot2; for(int i=1;i<n;i++) { if(pos==n) pos=0; tot=query2(1,pos+1,n); if(tot>=m) pos=query1(1,pos+1,m); else { k=m-tot; tot2=query2(1,1,n); k%=tot2; if(!k) k=tot2; pos=query3(1,k); } change(1,pos); } printf("%d\n",query3(1,1)); } } 线段树(做麻烦了)
模拟所有人,出局所有人中的第几个人
模拟场上还有几个人,出局场上第几个人
http://www.cnblogs.com/IUUUUUUUskyyy/p/6216855.html
#include <cstdio> using namespace std; struct node { int l,r,dis,mid; void mid_() { mid=(l+r)>>1; } }; struct node tree[1000000*4+1]; int n,m; inline void tree_up(int now) { tree[now].dis=tree[now<<1].dis+tree[now<<1|1].dis; } void tree_build(int now,int l,int r) { tree[now].l=l,tree[now].r=r; if(l==r) { tree[now].dis=1; return ; } tree[now].mid_(); tree_build(now<<1,l,tree[now].mid); tree_build(now<<1|1,tree[now].mid+1,r); tree_up(now); return ; } int tree_out(int now,int ci) { if(tree[now].l==tree[now].r) { tree[now].dis=0; return tree[now].l; } if(tree[now<<1].dis<ci) ci=tree_out(now<<1|1,ci-tree[now<<1].dis); else ci=tree_out(now<<1,ci); tree_up(now); return ci; } int main() { scanf("%d%d",&n,&m); tree_build(1,1,n); int now=0; do { now=(now-1+m)%n; if(n>1) tree_out(1,now+1); else printf("%d ",tree_out(1,now+1)); } while(--n); return 0; }
#include<cstdio> using namespace std; int main() { int n,k,ans=0; scanf("%d%d",&n,&k); for(int i=2;i<=n;i++) ans=(ans+k)%i; printf("%d",ans+1); }
某大佬的推导过程http://book.51cto.com/art/201403/433941.htm
注意:此方法不能输出过程