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

来源:互联网 发布:mac上wine怎么用 编辑:程序博客网 时间:2024/05/25 05:35

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(1n5000) 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 n1 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<T5000), 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
223
 

Sample Output
22Hint: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[N][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[n][0]+1);    }    return 0;}


1 0
原创粉丝点击