Wannafly挑战赛15 C 出队 模拟约瑟夫环

题目描述 

约瑟夫问题(https://baike.baidu.com/item/约瑟夫问题),n个人,1 2报数 1出队( 就是体育课的时候1 2报数 1出队,2留下),q次询问,每次求第x个人是第几个出队的

输入描述:

第一行两个数n,q
接下来q行,每行一个数x,表示询问

输出描述:

一行输出一个询问的答案
示例1

输入

4 3
2
3
4

输出

3
2
4

说明

1 2 3 4围成一圈,第一轮:1 2报数,1出队,2留下,3出队,4留下,第二轮,2出队,4留下

备注:

q≤500000
n和x≤1e18



题解:

递归模拟:

递归基: n = 1 时 直接放回1

设定一个bool值d 表示该圈是选择奇数还是选择偶数,起始时选择的是奇数,所以d = 1 (1,3,5..)

当n为奇数时且d为1时,下一个环d = 0。

当n为偶数时且d为0时,下一个环d = 1。

上式读者可以画图验证。

tot表示当前环删除了多少个。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll work(ll n,ll m,bool d) {
    if(n == 1) return 1;
    if((m & 1) == d) return ((m-1) >> 1) + 1;
    ll tot;
    if(d) tot = ((n-1) >> 1)+ 1;
    else tot = n >> 1;
    m = d ? m >> 1 : (m >> 1) + 1;
    d = d ^ (n & 1);
    return work(n - tot, m ,d) + tot;
}
int main()
{
    ll n,m;
    int q;
    while(~scanf("%lld%d",&n,&q))
    {
        while(q--) {
            scanf("%lld",&m);
            printf("%lld\n",work(n,m,1));
        }
        return 0;
    }
}



猜你喜欢

转载自blog.csdn.net/m0_38013346/article/details/80290172