zoukankan      html  css  js  c++  java
  • hdu 5860 Death Sequence(递推+脑洞)

    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.
     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).
     Output
    For each query m, output the m-th number in the death sequence.
    Sample Input
    1 7 2 7 1 2 3 4 5 6 7
     
    将约瑟夫环拉成一条直线,一开始一共n个人,每次从第一个人开始(杀掉第一个)从前向后依次每隔k个人杀一个人,最后大家都被干掉了,然后就形成了一个死亡序列
    有m次询问,问你在死亡序列中的第x个人编号是多少.
     
    思路:
    如果我们把他们的下标从0开始,那么第一批死的人下标肯定满足i%k==0
    继续想,杀掉一批人以后活着的人会向前补空位,加上第i个人在这轮没有被杀,那么他下轮的位置就会在i-i/k-1.
    换句话说第i个人会比第i-i/k-1多活一轮
    然后我们发现我们花O(n)的时间就能递推出每个人是在第几轮的第几个死的.
    我们开一个pair 保存每个人是 第几轮 和第几个
    我们再对轮数取个前缀和.就能知道他在总队列里面是第几个了
    一开始想到补空位的想法了,但是没有深想,利用递推的思路,其实在线性时间内就可以求出答案了
    代码如下:
     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 const int maxn=3e6+5;
     5 int cnt[maxn];
     6 int ans[maxn];//最后的答案
     7 int n,k,q;
     8 pair<int,int> dp[maxn];
     9 int main()
    10 {
    11     //freopen("de.txt","r",stdin);
    12     int t;
    13     scanf("%d",&t);
    14     while (t--){
    15         scanf("%d%d%d",&n,&k,&q);
    16         memset(cnt,0,sizeof cnt);
    17         for (int i=0;i<n;++i){
    18             dp[i].first=i%k?(dp[i-i/k-1].first+1):0;
    19             dp[i].second=cnt[dp[i].first]++;//求出来第i人的轮数,相应轮数cnt++
    20         }
    21         for (int i=0;i<maxn;++i){
    22             if (cnt[i]==0)
    23                 break;
    24             cnt[i]+=cnt[i-1];//处理前缀和,即第i轮之前一共杀死多少人
    25         }
    26         for (int i=0;i<n;++i){
    27             ans[(dp[i].first?cnt[dp[i].first-1]:0)+dp[i].second]=i;
    28         }
    29         for (int i=0;i<q;++i){
    30             int x;
    31             scanf("%d",&x);
    32             printf("%d
    ",ans[x-1]+1);
    33         }
    34     }
    35     return 0;
    36 }
     
  • 相关阅读:
    C++宏定义详解
    编写Qt Designer自定义控件 MyPlugins
    关于MFC共享DLL的模块状态切换 .
    QT 与 MFC 的区别 .
    typedef
    C++ floor函数
    C++ floor函数 截断浮点数小数部分 转
    MFC的多国语言界面的实现 转
    新工作 Day16 周五
    新工作 Day15 周四
  • 原文地址:https://www.cnblogs.com/agenthtb/p/6783636.html
Copyright © 2011-2022 走看看