HDU 5860 Death Sequence(死亡序列)

HDU 5860 Death Sequence(死亡序列)

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

 

Problem Description - 题目描述
You may heard of the Joseph Problem, the story comes from a Jewish historian living in 1st century. He and his 40 comrade soldiers were trapped in a cave, the exit of which was blocked by Romans. They chose suicide over capture and decided that they would form a circle and start killing themselves using a step of three. Josephus states that by luck or maybe by the hand of God, he and another man remained the last and gave up to the Romans. 
 
Now the problem is much easier: we have N men stand in a line and labeled from 1 to N, for each round, we choose the first man, the k+1-th one, the 2*k+1-th one and so on, until the end of the line. These poor guys will be kicked out of the line and we will execute them immediately (may be head chop, or just shoot them, whatever), and then we start the next round with the remaining guys. The little difference between the Romans and us is, in our version of story, NO ONE SURVIVES. Your goal is to find out the death sequence of the man. 
 
For example, we have N = 7 prisoners, and we decided to kill every k=2 people in the line. At the beginning, the line looks like this: 
1 2 3 4 5 6 7 

 

after the first round, 1 3 5 7 will be executed, we have
 2 4 6

 

and then, we will kill 2 6 in the second round. At last 4 will be executed. So, you need to output 1 3 5 7 2 6 4. Easy, right? 
 
But the output maybe too large, we will give you Q queries, each one contains a number m, you need to tell me the m-th number in the death sequence.
你可能听说过约瑟夫问题,这个故事来源于公元1世纪的犹太历史学家。他和40位战友被困在一个山洞中,洞口盘踞这罗马人。他们宁死不从,于是围成一个圈,每此经过两个人自杀一人。约瑟夫似乎得“天神眷顾”,和另一人得以苟活,降于罗马人。

现在这个问题更加简单:现有N个从1到N编号的人,每回合选择第1人,第k+1人,第2*k+1人,以此类推直至末尾。这些可怜虫会被即刻揪出行刑(或斩首,或枪毙,或其他),剩余的人则开始下一回合。我们的故事与罗马版略有不同,魔劫千万,生机尽灭。你的任务是找出这些人的死亡序列。

举个例子,现有N = 7个人,我们选择杀死队伍中k=2的人。一开始的队伍如下:

1 2 3 4 5 6 7

第一回合后,1 3 5 7卒,还剩

2 4 6

随后,我们在第二回合杀死2 6。4最后死。因此你需要输出1 3 5 7 2 6 4。简单否?

然而这样输出太长了,我们会给你Q个询问,每个询问有一个数字m,你需要输出死亡序列第m个数。
CN

 

Input - 输入
Multiple cases. The first line contains a number T, means the number of test case.
For every case, there will be three integers N (1<=N<=3000000), K(1<=K), and Q(1<=Q<=1000000), which indicate the number of prisoners, the step length of killing, and the number of query.
Next Q lines, each line contains one number m(1<=m<=n).
多组用例。第一行为一个整数T,表示测试用例的数量。
对于每个测试用例,有三个整数N (1<=N<=3000000),K(1<=K),和Q(1<=Q<=1000000),分别表示囚徒的数量,死亡间隔数,还有询问的数量。
随后N行,每行有一个整数m(1<=m<=n)。
CN

Output - 输出
For each query m, output the m-th number in the death sequence.
对于每个询问m,输出死亡序列中第m个数。
CN

 

Sample Input - 输入样例

1
7 2 7
1
2
3
4
5
6
7

 

Sample Output - 输出样例

1
3
5
7
2
6
4

 

题解

  动态规划。
  为了取模方便,可以从0开始。
  用turn[i]表示,表示当前位置可以存活多少轮,利用下一轮中的位置比本轮中的位置多苟活1s,可以用得到当前的苟活数。
  即:turn[i] = i%k ? turn[i - i / k - 1] + 1 : 0
  还能再用一个数组sum算出每回合死亡的人生,为了最后的输出做准备。

 

代码 C++

 1 #include <cstdio>
 2 #define  mx 3000005
 3 int turn[mx], sum[mx], opt[mx];
 4 int main(){
 5     int t, n, k, q, m, i, j;
 6     for (scanf("%d", &t); t; --t){
 7         scanf("%d%d%d", &n, &k, &q);
 8         sum[0] = 0;
 9         for (j = n, i = 1; j; ++i){
10             sum[i] = j / k;
11             if (j%k) ++sum[i];
12             j -= sum[i];
13             sum[i] += sum[i - 1];
14         }
15         for (i = 0; i < n; ++i){
16             turn[i] = i%k ? turn[i - i / k - 1] + 1 : 0;
17             opt[++sum[turn[i]]] = i + 1;
18         }
19         for (i = 0; i < q; ++i){
20             scanf("%d", &m);
21             printf("%d\n", opt[m]);
22         }
23     }
24     return 0;
25 }

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/Simon-X/p/6011895.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值