题目大意:
最开始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;
}
}