题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5643

这道题是一个类似于约瑟夫环的问题,但是跳动数每次都+1,小编先给出这道题的官方题解:


King's Game

约瑟夫问题的一个变种,然而题目全部是在唬人,就是一个简单的递推。虽然我知道有人会打表。。。

BestCoder Round #75 King 个人,每隔 BestCoder Round #75 King

BestCoder Round #75 King个人围成环,标号为BestCoder Round #75 KingBestCoder Round #75 King开始的好处是取模方便),每数BestCoder Round #75 King个人杀一个的情况下,最后一个存活的人的编号是BestCoder Round #75 King

BestCoder Round #75 King,这不需要解释。

BestCoder Round #75 King,第一个杀死的人的编号是BestCoder Round #75 King,杀死后只剩下BestCoder Round #75 King个人了,那么我们重新编号!

BestCoder Round #75 King号,也就是编号之间相差BestCoder Round #75 King我们只要知道现在BestCoder Round #75 King个人的情况最后是谁幸存也就知道BestCoder Round #75 King个人的情况是谁幸存。幸运的是BestCoder Round #75 King已经算出来了那BestCoder Round #75 King就是在BestCoder Round #75 King的基础上加上一个BestCoder Round #75 King即可不要忘记总是要取模。


BestCoder Round #75 King

BestCoder Round #75 King

BestCoder Round #75 King 个人删除,所以用 BestCoder Round #75 King 表示 BestCoder Round #75 King 个人,依次隔 BestCoder Round #75 King

BestCoder Round #75 King 号出局,从 BestCoder Round #75 King 开始新的一轮,从 BestCoder Round #75 King 开始清除,剩余 BestCoder Round #75 King

BestCoder Round #75 King

BestCoder Round #75 King(将标号转移到 BestCoder Round #75 King),问题轻松解决。

BestCoder Round #75 King,查询 BestCoder Round #75 King,总复杂度 BestCoder Round #75 King。由于可以滚动数组以及常数太小,所以 BestCoder Round #75 King 给了 BestCoder Round #75 King(其实是出题人不会别的算法嘿嘿嘿)。



比赛的时候由于太多时间浪费在了手机那倒水题上(小编TT),这道题并没有怎么看,当时看着觉得是模拟可能会超时,但是又想不出什么方法就没怎么看,下来看到题解的时候也是惊呆了,果然DP是个玄学啊,这东西还能这样递推……(好吧,是小编太辣鸡了),由于题解写的很清楚了,小编这里就只做一点小小的讲解就好,因为n个人最后留下来的那个人是确定的不会改变的,所以我们并不需要每次都去算一次,预处理打表就可以解决。


#include <cstdio>
#include <cstring>
const int maxn = 5000+5;
int ans[maxn];
int main()
{
ans[1] = 1;
for(int i=2; i<=5000; i++)
{
int tmp = 0;
for(int j=2; j<=i; j++)
{
tmp = (tmp+i-j+1) % j;
}
ans[i] = tmp+1;
}
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
printf("%d\n",ans[n]);
}
return 0;
}