牛客练习赛42C(枚举权值)
思路:既然无法枚举每个情况,那就枚举每个出现过的权值,加和。那么每个权值出现了多少次呢?用总数减去一次都选不中这个数的次数即可,类似概率的方法。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 const int maxn = 2001; 6 const int mod = 1e9 + 7; 7 int n, m, tot, invn, U, ans; 8 int id[maxn][maxn], val[maxn * maxn], f[maxn * maxn]; 9 struct node { 10 int val, x, y; 11 12 bool operator < (const node &rhs) const { 13 return val < rhs.val; 14 } 15 }a[maxn * maxn]; 16 17 inline int ksm(int a, int b) { 18 int ret = 1; 19 for (; b; b >>= 1) { 20 if (b & 1) ret = (ll)ret * a % mod; 21 a = (ll)a * a % mod; 22 } 23 return ret; 24 } 25 26 int main() { 27 ios_base::sync_with_stdio(0); 28 cin.tie(0); 29 30 cin >> n >> m; 31 invn = ksm(n, mod - 2), U = ksm(n, m); 32 33 for (int i = 1; i <= m; i++) { 34 for (int j = 1; j <= n; j++) { 35 int cid = (i - 1) * n + j; 36 cin >> a[cid].val; 37 a[cid].x = i, a[cid].y = j; 38 } 39 } 40 sort(a + 1, a + 1 + n * m); 41 for (int i = 1; i <= n * m; i++) { 42 tot += (i == 1 || a[i - 1].val != a[i].val); 43 id[a[i].x][a[i].y] = tot; 44 val[tot] = a[i].val; 45 } 46 47 for (int i = 1; i <= tot; i++) f[i] = 1; 48 for (int i = 1; i <= m; i++) { 49 sort(id[i] + 1, id[i] + 1 + n); 50 for (int j = 1, pos; j <= n; j = pos + 1) { 51 pos = j; 52 while (pos < n && id[i][pos] == id[i][pos + 1]) pos++; 53 f[id[i][j]] = (ll)f[id[i][j]] * (n - pos + j - 1) % mod * invn % mod; 54 } 55 } 56 57 for (int i = 1; i <= tot; i++) { 58 ans = ((ll)ans + (ll)val[i] * (U - (ll)f[i] * U % mod + mod) % mod) % mod; 59 } 60 cout << ans << endl; 61 62 return 0; 63 }