Codeforces 950D A Leapfrog in the Array ( 思维 && 模拟 )
题意 : 给出 N 表示有标号 1~N 的 N 个数,然后从下标 1 开始将这 N 个数每隔一位放置一个,直到 N 个数被安排完,现在有一个操作就是每次将数列中最右边的数向离其左边最近的空缺处填上,一直这样子填,直到下标 1~N 被填满,然后现在给出 Q 个询问,每个询问给出一个 X ,你需要回答下标为 X 的位置填放了什么数?
分析 :
初始状态每个数都处于奇数位,且可以根据位置下标得到具体的数是什么,即 num = (pos>>1) + 1
观察到当最后填充操作完成时,每个奇数位置的数是没有移动过所以其值是确定的
即 num = (pos>>1) + 1 ( pos%2 != 0 )
后面就是要处理偶数位置的情况,按照题意从初始到最后去模拟貌似并不好做
考虑从最终状态推回初始状态,对于每一个偶数位的数
举个例子 N = 4、考虑 1_243 时候的状态
在 3 下一步就移动到 _ 这个偶数位的时候,它左边是有 pos/2 个数的(奇数位置的数)
所以可以根据这个推出 3 移动到 _ 之后,它右边应有 N - (pos>>1) - 1 个数
所以如果是从 1324 逆推回 1_243 的时候 _ 这个偶数位置对应的值应当是 N - (pos>>1)
如果经过 N - (pos>>1) 这个移动后,位置处于奇数位,那么数就可以确定了
否则就继续移动,最后就能对于每一个偶数位采取逆推的方式来得到其值
#include<bits/stdc++.h> #define LL long long using namespace std; int main(void) { long long N, Q; scanf("%I64d %I64d", &N, &Q); while(Q--){ long long X; scanf("%I64d", &X); while(!(X&1)) X += (N - (X>>1)); printf("%I64d\n", (X>>1)+1); } return 0; }