传送门
题目看完立马就有想法的题。首先肯定不能二维做,先把矩阵拍成一维,以权值排序。然后肯定就是O(n)的做法。
根据题意,转移只能是单向的,那么大的权值肯定由小的转移而来,设dp为i位置值的期望
那么有转移:
d
p
[
i
]
=
∑
j
=
0
i
−
1
d
p
[
j
]
+
(
x
i
−
x
j
)
2
+
(
y
i
−
y
j
)
2
i
dp[i] = \frac{\sum_{j=0}^{i-1} dp[j] + (x_i-x_j)^2+(y_i - y_j)^2} {i}
dp[i]=i∑j=0i−1dp[j]+(xi−xj)2+(yi−yj)2
展开合并同类项易得
d
p
[
i
]
=
∑
j
=
0
i
−
1
(
d
p
[
j
]
+
x
j
2
+
y
j
2
)
+
i
∗
(
x
i
2
+
y
i
2
)
−
2
∗
∑
j
=
0
i
−
1
(
x
j
+
y
j
)
i
dp[i] = \frac{\sum_{j=0}^{i-1} (dp[j]+x_j^2+y_j^2) +i*(x_i^2+y_i^2) - 2 *\sum_{j=0}^{i-1} {(x_j+y_j)}}{i}
dp[i]=i∑j=0i−1(dp[j]+xj2+yj2)+i∗(xi2+yi2)−2∗∑j=0i−1(xj+yj)
很明显都可以用前缀和处理。
然后就是细节。。
要注意对于权值相同的点,我们需要对其特殊处理。
#include "bits/stdc++.h"
//#define int long long
using namespace std;
#define int long long
const int mod = 998244353;
const int N = 2e6 + 10;
#define pii pair<int,int>
struct node {
pii p;
int v;
};
vector<node> v;
int dp[N];
int sum1[N];
int sum2[N];
int sum3[N];
int sum4[N];
int quick_pow(int x, int b) {
int base = 1;
while (b) {
if (b & 1) {
base = (base * x) % mod;
}
x = (x * x) % mod;
b >>= 1;
}
return base;
}
void solve() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
int s;
cin >> s;
v.push_back(node{{i, j}, s});
}
}
sort(v.begin(), v.end(), [&](node a, node b) { return a.v < b.v; });
pii rt;
cin >> rt.first >> rt.second;
int pos = 0;
for (int i = 0; i < v.size(); ++i) {
if (rt.first == v[i].p.first && rt.second == v[i].p.second) {
pos = i;
break;
}
}
dp[0] = 0;
int last;
int last1, last2, last3, last4, lastp;
for (int i = 0; i < v.size(); ++i) {
int x = v[i].p.first;
int y = v[i].p.second;
if (i == 0) {
last1 = sum1[i] = x * x + y * y;
last2 = sum2[i] = x;
last3 = sum3[i] = y;
last4 = sum4[i] = dp[i];
last = v[i].v;
continue;
}
if (v[i].v == last) {
if (v[i].v == v[0].v) {
dp[i] = 0;
} else
dp[i] = (last4 + last1 - (2 * (last3 * y + last2 * x)) % mod + lastp * (x * x + y * y) % mod + mod) %mod *quick_pow(lastp, mod - 2) % mod;
} else {
dp[i] = (sum4[i - 1] + sum1[i - 1] - (2 * (sum3[i - 1] * y + sum2[i - 1] * x)) % mod +i * (x * x + y * y) % mod + mod) % mod *quick_pow(i, mod - 2) % mod;
last1 = sum1[i - 1];
last2 = sum2[i - 1];
last3 = sum3[i - 1];
last4 = sum4[i - 1];
lastp = i;
}
sum1[i] = (sum1[i - 1] + x * x + y * y) % mod;
sum2[i] = sum2[i - 1] + x;
sum3[i] = sum3[i - 1] + y;
sum4[i] = (sum4[i - 1] + dp[i]) % mod;
last = v[i].v;
}
cout << dp[pos] << endl;
}
signed main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
solve();
return 0;
}