hdu 5643 King's Game (dp约瑟夫环)
2016-03-15 17:46
246 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5643
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;
}
King's Game
Problem DescriptionIn 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;
}
相关文章推荐
- mysql心得
- nginx中的if嵌套
- phpstorm小总结
- 模板模式(7)
- iOS本地推送
- Eclipse代码提示功能失效
- 细说Angular ng-class
- MAC中在eclipse luna上搭建移动平台自己主动化測试框架(UIAutomator/Appium/Robotium/MonkeyRunner)关键点记录
- 从jvm源码解读Java运行时的类加载
- 安装mysql时 Write configuration file 错误的解决办法
- hdu 2089 不要62
- 基于java web的博客平台(六)
- MySQL查询:查询一个表中类别字段中Max()最大值对应的记录
- 我们的产品终于入驻淘宝服务市场
- 从Storm学习集群管理
- 关于sqlmap执行sql语句
- 几种简单的排序
- ft难点记录
- 深复制浅复制
- 李丰杰老师 实战生产管理专家