zoukankan      html  css  js  c++  java
  • Wannafly挑战赛15 C“出队”(约瑟夫环类问题)

    传送门

    参考资料

      [1]:

      [2]:Esquecer

      [3]:My CSDN

    题意

      n 个人围成一圈,1,2 报数,报 1 的离队,求编号为 x 的第几次出队;

    •对博文[1]的理解

      第一轮出队的编号一定为奇数,如果 x 为奇数,那么 x 一定在第一轮就出队了,ans = (x+1) / 2;

      如果 x 不为奇数,那么,执行的过程如下:

    1 while(x%2 == 0)
    2 {
    3     x /= 2;
    4     if(n&1)
    5         x++;
    6     ans += n/2;
    7     n -= n/2;
    8 }

      下面来解释一下上述代码的作用;

      ①如果 x 为偶数,那么在第一轮出队中,x 及其之前的偶数不出队,共 x/2 个编号;

      ②如果 n 为偶数,那么第一轮出队中共出队 n/2 个编号,还剩下 n/2 个编号,x 为剩下的编号中的第 x/2 个编号;

      在第二轮出队中,剩下的第一个编号依旧是第一个出队的编号,相当于剩下的 n/2 个编号重复一遍上述①②过程;

      如果 n 为奇数,那么第一轮出队中共出队 n/2+1 个编号,还剩下 n/2 个编号;

      但是,这剩下的 n/2 个编号在第二轮出队中,第一个出队的编号不再是第一个编号,而是第二个编号,与上述②过程不同;

      这该如何处理呢?

      很好办,在第一轮的出队中,让最后一个出队的编号 n 放到第二轮出队的队首位置,那么第二轮出队的编号中,第一个出对的依旧是第一个编号;

      其余编号的变化是在之前的基础上+1,接着重复上述①②过程;

    •Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 
     5 ll n,x;
     6 int q;
     7 
     8 ll Solve()
     9 {
    10     ll ans=0;
    11     ll cur=n;
    12     while(x%2 == 0)
    13     {
    14         x /= 2;///x及其之前共有x/2个编号
    15         if(cur&1)///如果当前剩余奇数个编号,将最后一个编号放到下一轮出队
    16             x++;
    17         ans += cur/2;
    18         cur -= cur/2;
    19     }
    20     ans += (x+1)/2;
    21     return ans;
    22 }
    23 int main()
    24 {
    25     scanf("%lld%d",&n,&q);
    26     while(q--)
    27     {
    28         scanf("%lld",&x);
    29         printf("%lld
    ",Solve());
    30     }
    31     return 0;
    32 }
    View Code

    •对博文[2]的理解

      

      短小精悍的代码,tql!

      如果 x 不为奇数,那么 x 肯定不再这一轮中出队,而 x 之前的偶数也不再这一轮中出队;

      即有 x/2 个编号不在这一轮中出队,那么相当于在这 n 个编号的队尾增加 x/2 个编号, x 变成队尾编号;

      接着执行上述过程;

    •Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 
     5 ll n,x;
     6 int q;
     7 
     8 ll Solve()
     9 {
    10     while(x%2 == 0)
    11         x=n+x/2;///将x/2个编号加入队尾,x变为队尾编号,并判断x是否可以在第一轮中出队
    12     return x/2+1;
    13 }
    14 int main()
    15 {
    16     scanf("%lld%d",&n,&q);
    17     while(q--)
    18     {
    19         scanf("%lld",&x);
    20         printf("%lld
    ",Solve());
    21     }
    22     return 0;
    23 }
    View Code
  • 相关阅读:
    help python(查看模块帮助文档)
    Vim常用快捷键
    tar 解压缩
    目前的学习计划
    学习方向
    C#转Python计划
    困惑的屌丝,求方向。。。
    修改PYTHONPATH的一种方法(在Window平台和Ubuntu下都有效)
    使用正则表达式统计vs项目代码总行数[转]
    日常工作细节汇总
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/11111440.html
Copyright © 2011-2022 走看看