专栏文章
题解:P13518 [KOI 2025 #2] 镜子
P13518题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miol3dem
- 此快照首次捕获于
- 2025/12/02 20:58 3 个月前
- 此快照最后确认于
- 2025/12/02 20:58 3 个月前
本题的关键在于:用所有 个镜子的位置和我的起始位置 ,表示出我的“最终位置”。
对称点计算
如果我在 位置,使用 位置的镜子,经过对称后我的位置在 (题目给出),此处给出证明过程:
- 若 ,根据距离计算方法,我与镜子的距离是 ,对称后我在镜子左侧,位置是 ;
- 若 ,同理,我与镜子的距离是 ,对称后我在镜子右侧,位置是 ;
- 若 ,对称后的位置也是 。
最终位置计算
现在,我们要将 个镜子 的位置按照一定顺序进行排序(这个顺序待会再讲,便于理解)。
设我第 次对称之前的位置是 ,排序后第 个镜子的位置是 。
那么对称后的位置就是 。
那么对称后的位置就是 。
同时,又有 。
所以推出:
所以推出:
设第 次对称后位置是 ,可以得到一个递推式:
现在来到了最关键的一步:观察正负号。
可以发现,上式中 前面是“”,而 前面是 “”。
然而,在 的表达式中, 前面又变成了 “”,而 前面变成了“”。
可以发现,上式中 前面是“”,而 前面是 “”。
然而,在 的表达式中, 前面又变成了 “”,而 前面变成了“”。
根据“负负得正”, 的表达式中,如果某个数的系数是 ,那么它在 中系数就是 ,在 中系数又是 。
继续找规律可以发现这个结论:在 的表达式中, 前的符号是 “”,而 前的符号是 “”。
也就是说,对于所有的 ,也对于排序前的 ,一共有 个正号“”以及 个负号“”要添加在这些数的前面。
此外,初始位置 前的符号还要分类讨论:
- 若 是奇数, 前符号是“”(因为第 次 前符号就是“”);
- 若 是偶数, 前符号是“”。
位置最大值
现在题目要求最终位置 的最大值。
为了让这个值最大,我们要尽可能让大的数前面使用 “”,小的数前面使用“”。
由此我们也得到了排序的原则:从大到小,前 个值前面用“”,其余的值(共 个)用“”。
不要忘记乘上它们每个镜子前的系数 。
由此我们也得到了排序的原则:从大到小,前 个值前面用“”,其余的值(共 个)用“”。
不要忘记乘上它们每个镜子前的系数 。
最后还要分情况讨论 前的系数是 还是 。
代码
CPP#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int n, s, a[N];
long long ans;
int main(){
cin >> n >> s;
for(int i=1; i<=n; i++)
cin >> a[i];
// 贪心 排序
sort(a + 1, a + n + 1, greater<int>());
// 正负号 统计答案
for(int i=1; i<=(n+1)/2; i++)
ans += a[i] * 2;
for(int i=(n+1)/2+1; i<=n; i++)
ans -= a[i] * 2;
// 分情况讨论
if(n % 2 == 0) ans += s;
else ans -= s;
cout << ans;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...