codeforces- 949B - A Leapfrog in the Array(思维)

题目大意: 
最开始n个数字中的数字i在位置2*i-1,之后从右向左依次用数字将该列填充。最后q个query问你pos为Xi该填上什么数字。

思路: 
首先n范围1e18,直接模拟肯定不行,但肯定有什么规律在里面,我们自己写写看: 

我们可以看出,数组中只有n个数字,所以位于n的位置左边的数字没有改变,就是xi/2 + 1;

证明以上的小小推论也很简单 

因为最初有2*n个位置,实际上只有n个数字,那么在最左边n个位置中的奇数位置的数字其实不可能发生移动。

之后我们考虑其他位置,我们一个数字(在位置pos)一次跳跃的前提是他相邻的左边有任意个连续的填充块, 

这左边所有的填充块中其中有pos/2个数字在最初就在他的左边,剩下还有n-pos/2个数字最初在他的右边,因此我们可以推出,如果逆推回去,设query中的位置为p,那么每一次跳跃后的位置就是p+(n-p/2),当(p+(n-p/2))&1时说明他到了最初的位置,这时候(New Xi)/2+1即为answer

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;

const int maxn = 1e5+7;

ll n, m, q;


int main()
{
        scanf("%lld%lld",&n,&q);
        while(q--)
        {
            ll x;
            scanf("%lld",&x);
            while(1)
            {
                if(x&1) break;
                x = x + (n - x/2);
            }
            cout << x/2 + 1 << endl;
        }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值