HDU 5643 King's Game (约瑟夫环问题的变形 递推)

本文探讨了一个变种的约瑟夫环问题,通过逐步淘汰指定编号的人来确定最后幸存者的编号。采用动态更新编号的方法,实现了简洁高效的求解算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大体题意:

有n 个人,进行比赛,第一轮比赛 从1开始报数,报到1的出局,第二轮报2,,,,  问最后谁没出局?

思路:

一看就是约瑟夫环问题的变型了。

在简单记录一下思考的过程吧:

n 个人 编号为0,1,2,,,,,n-1.

假设这一局k-1 出局了。

那么重新编号:

k  k+1 k+2,,,, n-1  0 1   k-2

0  1     2                           n-2

这n -2 个人进行比赛。

那么我们给他变回去即可!

怎么变呢? 显然是(x + k) % n = f[n]

但是这里k 是变化的,当i 为2 时  只有两个人  显然报数是 n-i+1.

详细见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int f[5007];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        f[1] = 0;
        for (int i = 2; i <= n; ++i){
            f[i] = (f[i-1] + n-i+1) % i;
        }
        printf("%d\n",f[n]+1);
    }
    return 0;
}


King's Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 703    Accepted Submission(s): 390


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
  
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.
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   6014  6013  6012  6011  6010 
 



### HDU 1443 约瑟夫问题解析 #### 题目描述 题目涉及的是经典的约瑟夫环问题的一个变种。给定一个整数 \( k \),表示有 \( k \) 个好人和 \( k \) 个坏人,总共 \( 2k \) 个人围成一圈。编号从 1 到 \( 2k \),其中前 \( k \) 个为好人,后 \( k \) 个为坏人。目标是在不杀死任何好人的前提下,找到可以先消灭所有坏人的最小步数 \( n \)[^5]。 #### 解题思路 为了确保在杀掉第一个好人之前能将所有的坏人都清除,可以通过模拟约瑟夫环的过程来寻找符合条件的最小步数 \( n \)。一种有效的方法是利用动态规划的思想逐步缩小范围直到找到最优解。对于较大的 \( k \),由于数值较大可能导致计算复杂度增加,因此需要考虑算法效率并进行适当优化[^1]。 #### Python 实现代码 下面提供了一个基于Python编写的解决方案: ```python def josephus(k): m = 2 * k def find_min_n(m, start=1): for n in range(1, m + 1): pos = (start + n - 2) % m + 1 if all((pos - i) % m > k or (pos - i) % m == 0 for i in range(n)): return n raise ValueError("No solution found") min_n = None for good_start in range(1, k + 1): try: current_min = find_min_n(m=m, start=good_start) if not min_n or current_min < min_n: min_n = current_min except ValueError as e: continue return min_n if __name__ == "__main__": test_cases = [int(input()) for _ in range(int(input()))] results = [] for case in test_cases: result = josephus(case) print(result) ``` 此段代码实现了上述提到的逻辑,并且能够处理多个测试案例。需要注意的是,在实际应用中可能还需要进一步调整参数以及边界条件以适应不同情况下的需求[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值