嘘~ 正在从服务器偷取页面 . . .

CF1042E Vasya and Magic Matrix 题解


CF1042E Vasya and Magic Matrix 题解

题目链接:Vasya and Magic Matrix

题意

瓦西亚得到了一个大小为 \(n \times m\) 的魔法矩阵 \(a\)。矩阵的行从上到下编号为 \(1\)\(n\),列从左到右编号为 \(1\)\(m\)。设 \(a_{ij}\) 是第 \(i\) 行和第 \(j\) 列的交点处的元素。

瓦西亚还得到了一个芯片。最初,芯片位于第 \(r\) 行和第 \(c\) 列的交点处(即元素 \(a_{rc}\) 处)。瓦西亚执行以下过程,只要可能:在所有矩阵元素中,其值小于芯片所在元素的值,瓦西亚随机且等概率地选择一个元素,并将芯片移动到该元素。

移动芯片后,他将其得分增加到这些元素之间的欧几里德距离的平方(即芯片现在所在的元素与芯片移动前所在的元素之间的距离)。当没有元素的值小于芯片所在元素的值时,过程结束。

矩阵元素之间的欧几里德距离,其坐标分别为 \((i_1, j_1)\)\((i_2, j_2)\),等于 \(\sqrt{(i_1-i_2)^2 + (j_1-j_2)^2}\)

计算瓦西亚最终得分的期望值。

可以证明答案可以表示为 \(\frac{P}{Q}\),其中 \(P\)\(Q\) 是互质的整数,并且 \(Q \not\equiv 0\pmod{998244353}\)。以 \(P \cdot Q^{-1} \pmod{998244353}\) 的形式输出值。

输入格式

输入的第一行包含两个整数 \(n\)\(m\) \((1 \le n, m \le 1,000)\) —— 矩阵 \(a\) 的行数和列数。

接下来的 \(n\) 行包含矩阵 \(a\) 的描述。第 \(i\) 行包含 \(m\) 个整数 \(a_{i1}, a_{i2}, \dots, a_{im}\) \((0 \le a_{ij} \le 10^9)\)

接下来的一行包含两个整数 \(r\)\(c\) \((1 \le r \le n, 1 \le c \le m)\) —— 芯片当前所在的行号和列号。

输出格式

以问题陈述中描述的格式输出瓦西亚最终得分的期望值。

因为一个点 \(i\) 只会被权值比 \(a_i\) 小的 \(j\) 贡献,所以我们可以先把所有的点按权值顺序排序。

\(f_i\) 表示第 \(i\) 个点作为起点的期望,记有 \(T\) 个点的权值小于 \(a_i\)\[ f_i = \frac{\sum_{a_j<a_i}\left( f_{j}+(x_i-x_j)^2+(y_i-y_j)^2\right)}{T} \] 因为已经排序过了,所以这个式子可以很好的前缀和优化,不过需要先把距离拆开来 \[ \begin{gathered} \left(x_i-x_j\right)^2+\left(y_i-y_j\right)^2=x_i^2-2 \times x_i \times x_j+x_j^2+y_i^2-2 \times y_i \times y_j+y_j^2 \\ =x_i^2+x_j^2+y_i^2+y_j^2-2 \times\left(x_i \times x_j+y_i \times y_j\right) \end{gathered} \] 于是我们只要维护 \(\sum x_j,~\sum y_j,~\sum(x_j^2+y_j^2),~\sum f_j\) 这四个量就可以 \(\mathcal{O}(\log V)\)​ 转移了

时间复杂度 \(\mathcal{O}(nm \log V)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
const int mod = 998244353;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
void add(int &x,int y) { (x += y) >= mod ? x -= mod : 0; }
#define N ((int)(1e6 + 15))
#define sq(x) ((x) * (x))

int tot, sumx, sumy, sump, sumdp, dp[N];
struct node { int x, y, v; } p[N];
int qpow(int a, int b)
{
    int r = 1;
    while(b)
    {
        if(b & 1) r = r * a % mod;
        b >>= 1; a = a * a % mod;
    }
    return r;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int n, m; cin >> n >> m;
    for(int i = 1; i <= n; i++)
        for(int j = 1, x; j <= m; j++) { cin >> x, p[++tot] = {i, j, x}; }
    int sx, sy; cin >> sx >> sy;
    sort(p + 1, p + 1 + tot, [](node a, node b) { return a.v < b.v; });
    for(int i = 1, l = 1; i <= tot; i++)
    {
        dp[i] = 0;
        if(p[i].v != p[l].v) {
            while(l < i) {
                add(sumx, p[l].x), add(sumy, p[l].y);
                add(sump, sq(p[l].x) + sq(p[l].y)); add(sumdp, dp[l]); ++l;
            }
        }
        add(dp[i], (l - 1) * (sq(p[i].x) + sq(p[i].y)) % mod);
        add(dp[i], mod - 2 * (p[i].x * sumx % mod + p[i].y * sumy % mod) % mod);
        add(dp[i], (sump + sumdp) % mod);
        dp[i] = dp[i] * qpow(l - 1, mod - 2) % mod;
        if(p[i].x == sx && p[i].y == sy) return cout << dp[i] << '\n', 0;
    }
    return 0;
}

参考文献

[1] https://www.luogu.com.cn/article/ecl7uhhf


题外话

ChatGPT 的翻译水平确实还可以,比机翻强多了。


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录