「题解 P7099」yLOI2020 灼
贴一下原题
好久没做过非传统高斯消元的期望类问题了, 由于终点只会被经过一次, 因此我们可以考虑从两个终点开始定义状态, 令靠近位置$pos$的两个端点为$l$和$r$, 到达任意终点的期望步数为$f_i$, 则有:
$f_i = \frac{1}{2}(f_{i+1} + f_{i-1})+1$
特殊的, $f_l=f_r=0$
$\because 2f_i = f_{i+1}+f_{i-1}+2$
$\therefore f_{i+1}-f{i}=f_{i}-f_{i-1}+2$
于是问题就转化为一道低于全国卷难度的数学题了
$\therefore 令g_i=f_{i+1}-f_i$
$\therefore g_i=g_{i-1}-2$, ${g_i}$为等差数列
$\therefore 设g_i=g_1-2(i-1)$
$\because \Sigma_{i=l}^{r-1} g_i=f_r-f_l=0$
$\therefore [g_1-2(l-1)+g_1-2(r-2)]*(r-1)/2=0$
$\therefore g_1=l+r-3$
$\therefore f_{pos}=f_{pos}-f_l=\Sigma_{i=l}^{pos-1}g_i=(r-pos)(pos-l)$
注意到输入中$y_i$单调不降, 那么我们一遍扫过去更新$l,r$即可
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
const int MOD = 998244353;
int T, n, q;
int pos[MAXN];
long long ans, ans1, ans2, ans3, ans4;
int main()
{
scanf("%d%d%d", &T, &n, &q);
for (int i = 1; i <= n; i++)
scanf("%d", &pos[i]);
sort(pos + 1, pos + n + 1);
int nex = 1;
ans4 = 1e18;
for (int i = 1; i <= q; i++)
{
int npos;
scanf("%d", &npos);
while (npos > pos[nex]) nex++;
ans = 1LL * (npos - pos[nex - 1]) * (pos[nex] - npos) % MOD;
ans1 ^= ans;
ans2 += ans & 1;
ans3 = max(ans3, ans);
ans4 = min(ans4, ans);
}
printf("%lld\n%lld\n%lld\n%lld", ans1, ans2, ans3, ans4);
return 0;
}