2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)
Posted shuaihui520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5860
题目大意:给你n个人排成一列编号,每次杀第一个人第i×k+1个人一直杀到没的杀。然后剩下的人重新编号从1~剩余的人数。按照上面的方式杀。问第几次杀的是谁。
分析
一轮过后和原来问题比只是人的编号发生变化,故可以转化为子问题求解,不妨设这n个人的编号是0~n-1,对于第i个人,如果i%k=0,那么这个人一定是第一轮出列的第i/k+1个人;如果i%k!=0,那么这个人下一轮的编号就是i-i/k-1;
#include<stdio.h> #include<algorithm> using namespace std ; #define N 3000000+10 struct no { int d ; ///表示哪一轮被杀 int num ; ///表示当前轮第几个被杀 int p ; ///表示本身是几号 }s[N]; bool cmp(no a , no b) { if(a.d==b.d) return a.num<b.num; return a.d<b.d; } int main( ) { int T,n,k,q,m; scanf("%d",&T); while(T--) { scanf("%d %d %d",&n,&k,&q); s[0].num=1; for(int i=0 ; i<n ; i++) { s[i].p=i+1; if(i%k==0) { s[i].d=1; if(i==0) continue; s[i].num=s[i-k].num+1; } else { s[i].d=s[i-i/k-1].d+1; s[i].num=s[i-i/k-1].num; } } sort(s,s+n,cmp); while(q--) { scanf("%d",&m); m--; printf("%d ",s[m].p); } } }
以上是关于2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)的主要内容,如果未能解决你的问题,请参考以下文章
2016 Multi-University Training Contest 2题解报告
2016 Multi-University Training Contest 1 D HDU 5762 GCD
2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)
2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)