您的位置:首页 > 其它

hdu 5643 King's Game (dp约瑟夫环)

2016-03-15 17:46 246 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5643


King's Game

Problem Description

In order to remember history, King plans to play losephus problem in the parade gap.He calls n(1≤n≤5000) soldiers,
counterclockwise in a circle, in label 1,2,3...n.

The first round, the first person with label 1 counts
off, and the man who report number 1 is
out.

The second round, the next person of the person who is out in the last round counts off, and the man who report number 2 is
out.

The third round, the next person of the person who is out in the last round counts off, and the person who report number 3 is
out.

The N - 1 round, the next person of the person who is out in the last round counts off, and the person who report number n−1 is
out.

And the last man is survivor. Do you know the label of the survivor?

 

Input

The first line contains a number T(0<T≤5000),
the number of the testcases.

For each test case, there are only one line, containing one integer n,
representing the number of players.

 

Output

Output exactly T lines.
For each test case, print the label of the survivor.

 

Sample Input

2
2
3

 

Sample Output

2
2

Hint:
For test case #1:the man who report number $1$ is the man with label $1$, so the man with label $2$ is survivor.

For test case #1:the man who report number $1$ is the man with label $1$, so the man with label 1 is out. Again the the man with label 2 counts $1$, the man with label $3$ counts $2$, so the man who report number $2$ is the man with label $3$. At last the man with label $2$ is survivor.

 

问题描述:n个人(编号1~n),从1开始报数,报到m的退出,剩下的人继续从1开始报数。求胜利者的编号。数学解法复杂度:O(n)。

无论是用链表实现还是用数组实现都有一个共同点:要模拟整个游戏过程,不仅程序写起来比 较烦,而且时间复杂度高达O(nm),当n,m非常大(例如上百万,上千万)的时候,几乎是没有办法在短时间内出结果的。我们注意到原问题仅仅是要求出最 后的胜利者的序号,而不是要读者模拟整个过程。因此如果要追求效率,就要打破常规,实施一点数学策略。

为了讨论方便,先把问题稍微改变一下,并不影响原意:

问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求胜利者的编号。

5个人

n个人的标号:1 2 3 4 5

对应的下标:  0 1 2 3 4

i=1 第一次报数:  x 0 1 2 3

i=2 第二次报数:  x 2 x 0 1

i=3 第三次报数:  x x x 0 1

i=4 第四次报数:  x x x 0
x

上图就是模拟的过程,那么最后胜利的人num在前一次(i)报数过程中的下标为 (num + i)% (n-i);#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;

#define N 5010
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define met(a, b) memset(a, b, sizeof (a))
typedef long long LL;

int dp
[2];

int main ()
{
int t, n;
scanf ("%d", &t);

for (int i=2; i<N; i++)
{
for (int j=i-2; j>=0; j--)
{
dp[i][j%2] = (dp[i][(j%2)^1] + j+1) % (i-j);
}
}

while (t--)
{
scanf ("%d", &n);
printf ("%d\n", dp
[0]+1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: