牛客练习赛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 }
原文地址:https://www.cnblogs.com/AlphaWA/p/10541474.html