HDU5643-King's Game

BestCoder上的题,直接贴网站上的题目和题解了。很棒的题。

问题描述
为了铭记历史,国王准备在阅兵的间隙玩约瑟夫游戏。它召来了 n(1≤n≤5000) 个士兵,逆时针围成一个圈,依次标号 1,2,3...n。
第一轮第一个人从 1 开始报数,报到 1 就停止且报到 1 的这个人出局。
第二轮从上一轮出局的人的下一个人开始从 1 报数,报到 2 就停止且报到 2 的这个人出局。
第三轮从上一轮出局的人的下一个人开始从 1 报数,报到 3 就停止且报到 3 的这个人出局。
第 n-1 轮从上一轮出局的人的下一个人开始从 1 报数,报到 n-1 就停止且报到 n-1 的这个人出局。
最后剩余的人是幸存者,请问这个人的标号是多少?
输入描述
第一行一个整数表示测试组数:T(0<T≤5000) 。
每组数据占一行,包含一个整数 n,表示 n 个人围成一圈。
输出描述
共 T 行。对每组数据,输出幸存者的编号。
输入样例
2
2
3
输出样例
2
2
Hint
对于第一组数据,一开始报到 1 的人即标号为 1 的人退出,幸存者是 2 号。
对于第二组数据,一开始报到 1 的人即标号 1 的人退出。接着 2 号报 1,3 号报 2,报到 2 的人即 3 号退出。幸存者是 2 号。

题解:

约瑟夫问题的一个变种,然而题目全部是在唬人,就是一个简单的递推。虽然我知道有人会打表。。。
我们看看裸的约瑟夫是怎么玩的:n 个人,每隔 k 个删除。
由于我们只关心最后一个被删除的人,并不关心最后的过程,所以,我们没有必要也不能够模拟整个过程。我们用递推解决。假设有n个人围成环,标号为[0,n-1]从0开始的好处是取模方便),每数k个人杀一个的情况下,最后一个存活的人的编号是f[n]。
我们有f[1]=0,这不需要解释。
接着考虑一般情况f[n],第一个杀死的人的编号是k-1,杀死后只剩下n-1个人了,那么我们重新编号!
原来编号为k的现在是0号,也就是编号之间相差3我们只要知道现在n-1个人的情况最后是谁幸存也就知道n个人的情况是谁幸存。幸运的是f[n-1]已经算出来了那f[n]就是在f[n-1]的基础上加上一个k即可不要忘记总是要取模。

所以递推式子是: f[i]={ 0 i=1   (f[i - 1] + k) mod i other
此题只用在原版约瑟夫问题上加一维,由于依次隔 1,2,3...n-1个人删除,所以用 f[i][j]表示 i个人,依次隔 j,j+1...j+i-1 个人的幸存者标号。
根据刚才的重标号法,第一次 j-1 号出局,从 j 开始新的一轮,从 j+1 开始清除,剩余 i-1 个人,也有递推式子:
f[i][j]={ 0  i=1 (f[i - 1][j+1] + j) mod i other
答案就是 f[n][1]+1(将标号转移到 [1,n]),问题轻松解决。
复杂度:预处理 O(n^2),查询 O(1),总复杂度 O(n^2)。由于可以滚动数组以及常数太小,所以 n 给了 5000。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 5010;

int f[2][N]; // f[i][j]表示i个人 依次隔j,j+1...j+i−1个人删除的幸存者标号
// f[i][j]=(f[i-1][j+1]+j)%i
int ans[N];

int main()
{
    f[0][0] = 0;
    for (int i = 0; i < 5000; ++i)
        f[1][i] = 0;   // 1个人的时候幸存者永远是0
    for (int i = 1; i <= 5000; ++i) {
        for (int j = 1; j <= 5000; ++j) {
            f[i%2][j] = (f[(i - 1)%2][j + 1] + j) % i;
        }
        ans[i] = f[i%2][1];
    }
    int t;
    scanf("%d", &t);
    while (t--) {
        int n;
        scanf("%d", &n);
        printf("%d\n", ans[n] + 1);
    }
    return 0;
}

HDU5643-King's Game

时间: 2024-10-15 06:42:00

HDU5643-King's Game的相关文章

hdu-5643 King&#39;s Game(打表)

题目链接: King's Game Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 200    Accepted Submission(s): 115 Problem Description In order to remember history, King plans to play losephus problem in the

POJ2728 Desert King

Time Limit: 3000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu Description David the Great has just become the king of a desert country. To win the respect of his people, he decided to build channels all over his country to bring water to

hdu 5640 King&#39;s Cake(模拟)

Problem Description It is the king's birthday before the military parade . The ministers prepared a rectangle cake of size n×m(1≤n,m≤10000) . The king plans to cut the cake himself. But he has a strange habit of cutting cakes. Each time, he will cut

[SCOI2005]互不侵犯King

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4255  Solved: 2458 [Submit][Status][Discuss] Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <=

01分数规划+prim POJ2728 Desert King

Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 26009   Accepted: 7219 Description David the Great has just become the king of a desert country. To win the respect of his people, he decided to build channels all over his coun

POJ3682 King Arthur&#39;s Birthday Celebration

King Arthur is an narcissist who intends to spare no coins to celebrate his coming K-th birthday. The luxurious celebration will start on his birthday and King Arthur decides to let fate tell when to stop it. Every day he will toss a coin which has p

hdu_5314_Happy King(树的点分治)

题目链接:hdu_5314_Happy King 题意: 给出一颗n个结点的树,点上有权值: 求点对(x,y)满足x!=y且x到y的路径上最大值与最小值的差<=D: 题解: 还是树的点分治,在统计答案的时候先按到根的最小值排序,然后用最大值减D去找有多少个满足答案. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef pair<i

codeforces 710A A. King Moves(水题)

题目链接: A. King Moves 题意: 给出king的位置,问有几个可移动的位置; 思路: 水题,没有思路; AC代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <bits/stdc++.h> #include <stack> #include &l

hdu 5641 King&#39;s Phone(暴力模拟题)

Problem Description In a military parade, the King sees lots of new things, including an Andriod Phone. He becomes interested in the pattern lock screen. The pattern interface is a 3×3 square lattice, the three points in the first line are labeled as

hdu 5642 King&#39;s Order

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5642 题意:给出一个n,问一个长度为n的只含有小写字母的序列中,满足其中不含有超过3个连续相同字母的序列的个数有多少. 思路: 设dp[i][j],表示序列第i位为字母j的合法序列的个数.sum[i]表示长度为i的序列有多少个. 假设第i位为字母'a',dp[i][j]就是sum[i-1]*1-不合法的情况. 不合法的情况就是sum[i-4] - dp[i-4][j]. sum[i-4]表示已经计算