解题思路
核心观察:每次使用镜子相当于进行一次对称变换,位置从 a 变为 2b - a。经过数学推导可以发现,最终的终点位置可以表示为:
终点 = 2×(某些镜子的位置) - 2×(另一些镜子的位置) + ... + (-1)^N × 初始位置
关键规律:
-
当镜子数量为偶数时,最终位置与初始位置的符号相同
-
当镜子数量为奇数时,最终位置与初始位置的符号相反
-
要最大化最终位置,需要让正系数的镜子位置尽可能大,负系数的镜子位置尽可能小
算法策略:
-
n=1或2:直接模拟所有可能的顺序
-
n为偶数且初始位置在两个中间镜子之间:采用交替左右跳跃的策略
-
其他情况:根据n的奇偶性决定起始跳跃方向,然后交替左右跳跃
#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 2e5 + 10,inf = 0x3f3f3f3f; ll n,k,a[N]; // n:镜子数量, k:初始位置, a:镜子位置数组 ll ans;// 处理n=1或2的情况:直接模拟所有可能的顺序 void solve1(){if(n == 1) k = 2 * a[1] - k; // 只有一个镜子,直接对称if(n == 2) {// 两个镜子,按顺序1->2使用k = 2 * a[1] - k;k = 2 * a[2] - k;} }// 处理子任务2和3的情况:n为偶数且初始位置在两个中间镜子之间 void solve2(){int L = 1,R = n,id = 1; // L,R:左右指针, id:标识当前跳跃方向while(L <= R){if(id % 2 == 1) k = 2 * a[L] - k,L++; // 奇数步:用左边镜子,向右跳if(id % 2 == 0) k = 2 * a[R] - k,R--; // 偶数步:用右边镜子,向左跳id++;} }// 处理子任务4的情况:一般情况 void solve4(){int L = 1,R = n,id;// 根据n的奇偶性决定起始跳跃方向if(n % 2 == 1) id = 0; // n为奇数:实现最开始往右跳if(n % 2 == 0) id = 1; // n为偶数:默认从左开始跳while(L <= R){if(id % 2 == 1) k = 2 * a[L] - k,L++; // 用左边镜子if(id % 2 == 0) k = 2 * a[R] - k,R--; // 用右边镜子id++;} }int main() {cin >> n >> k;for(int i = 1; i <= n; i++) cin >> a[i];// 根据不同的情况选择相应的解法if(n == 1 || n == 2) solve1(); // 情况1:镜子数量少,直接模拟else if(n % 2 == 0 && a[n / 2] < k && k < a[n / 2 + 1]){ // 子任务2,3:偶数且初始位置在中间 solve2(); }else{ // 子任务4:其他所有情况 solve4();} cout << k << endl; // 输出最终位置return 0; }