Editorial for Expected Cells (Stretch)
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
Approach
Do not enumerate pairs of sampled cells. For each grid cell let
.
The area is , so
.
Cell is outside the sampled bounding rectangle if and only if both sampled
cells lie strictly to one side of it: both left of column
, both right, both above row
, or both below. Let
be the total weights of those four strict sides, and
let
be the total weights of the four strict quadrants. Writing
for
the total weight, inclusion-exclusion gives
~\Pr((r, c)\text{ inside}) = 1
- \frac{L^2 + R^2 + U^2 + D^2}{W^2}
- \frac{NW^2 + NE^2 + SW^2 + SE^2}{W^2}~.
All eight region weights are from a two-dimensional prefix sum together with the
global row and column totals. Summing over every cell is
.
A pairwise enumeration of sampled cells is and is too slow.
Solution (C++)
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
long long modpow(long long a, long long e) {
long long r = 1;
a %= MOD;
while (e) {
if (e & 1) {
r = r * a % MOD;
}
a = a * a % MOD;
e >>= 1;
}
return r;
}
long long sqmod(long long x) {
x %= MOD;
if (x < 0) {
x += MOD;
}
return x * x % MOD;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
vector<vector<long long> > pref(n + 1, vector<long long>(m + 1, 0));
for (int r = 1; r <= n; r++) {
for (int c = 1; c <= m; c++) {
long long w;
cin >> w;
pref[r][c] = w + pref[r - 1][c] + pref[r][c - 1] - pref[r - 1][c - 1];
}
}
auto rect = [&](int r1, int c1, int r2, int c2) -> long long {
if (r1 > r2 || c1 > c2 || r1 < 1 || c1 < 1 || r2 > n || c2 > m) {
return 0;
}
return pref[r2][c2] - pref[r1 - 1][c2] - pref[r2][c1 - 1] + pref[r1 - 1][c1 - 1];
};
long long W = pref[n][m];
long long W2 = sqmod(W);
long long num = 0;
for (int r = 1; r <= n; r++) {
for (int c = 1; c <= m; c++) {
long long L = rect(1, 1, n, c - 1);
long long R = rect(1, c + 1, n, m);
long long U = rect(1, 1, r - 1, m);
long long D = rect(r + 1, 1, n, m);
long long NW = rect(1, 1, r - 1, c - 1);
long long NE = rect(1, c + 1, r - 1, m);
long long SW = rect(r + 1, 1, n, c - 1);
long long SE = rect(r + 1, c + 1, n, m);
long long bad = (sqmod(L) + sqmod(R) + sqmod(U) + sqmod(D)) % MOD;
long long add = (sqmod(NW) + sqmod(NE) + sqmod(SW) + sqmod(SE)) % MOD;
long long term = (W2 - bad + add) % MOD;
if (term < 0) {
term += MOD;
}
num += term;
if (num >= 4LL * MOD) {
num %= MOD;
}
}
}
num %= MOD;
cout << num * modpow(W2, MOD - 2) % MOD << "\n";
}
Comments