【Messages】

定义X=inxiX=\sum_{i}^nx_i读到需要的信息的学生的数量,其中xix_i为第ii个学生是否读到自己需要的信息,如果读到就为11,否则为00

根据期望的可加性可知:

E(X)=E(x1)+E(x2)+..+E(xn)\mathbb{E}(X)=\mathbb{E}(x_1)+\mathbb{E}(x_2)+..+\mathbb{E}(x_n)

对于每一个E(xi)\mathbb{E}(x_i)来说:

E(xi)=1P(imi)+0P(imi)=1P(imi)=Pi\begin{matrix} \mathbb{E}(x_i)&=&1\cdot P(第i个学生读到m_i)+0\cdot P(第i个学生没有读到m_i) \\ \\ &=&1\cdot P(第i个学生读到m_i) \\ \\ &=&P_i \end{matrix}

故:

E(X)=i=1nE(xi)=i=1nPi\mathbb{E}(X)=\sum_{i=1}^n\mathbb{E}(x_i)=\sum_{i=1}^nP_i

若顶置的消息集合为: U=<u1,u2,...,ut>U=<u_1,u_2,...,u_t>,则:

Pi={0,miU1,miUtkikit,miUt>kiP_i= \begin{cases} 0, & 如果m_i\notin U \\ 1, & 如果m_i\in U且t\le k_i \\ \frac{k_i}{t}, & 如果m_i\in U且t> k_i \end{cases}

因为我们要选取一个集合UU使得期望E(X)\mathbb{E}(X)最大,所以当tt固定时,我们可以贪心的选取集合UU

又因1ki201\le k_i\le 20,故当nt>20n\ge t> 20时,Pi=kitP_i=\frac{k_i}{t}

E(X)=i=1nPi=i=1nkit=1ti=1nki\mathbb{E}(X)=\sum_{i=1}^nP_i=\sum_{i=1}^n\frac{k_i}{t}=\frac{1}{t}\sum_{i=1}^nk_i

需要先将kik_i的值排序并做前缀和,然后再枚举tt的值。

t20t\le 20时,可以暴力枚举。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, m[N], k[N];

double f(int t) {  // 固定t时的最优选取
    unordered_map<int, double> val;
    for (int i = 1; i <= n; i++) {
        if (t <= k[i])
            val[m[i]] += 1;
        else
            val[m[i]] += (1.0 * k[i]) / t;
    }
    vector<pair<int, double>> vec;
    for (auto it : val) vec.push_back({it.first, it.second});
    sort(vec.begin(), vec.end(),
         [](auto a, auto b) { return a.second > b.second; });

    double sum = 0;
    for (int i = 0; i < min(t, (int)vec.size()); i++) sum += vec[i].second;
    return sum;
}

void print(int t) {
    unordered_map<int, double> val;
    for (int i = 1; i <= n; i++) {
        if (t <= k[i])
            val[m[i]] += 1;
        else
            val[m[i]] += 1.0 * k[i] / t;
    }
    vector<pair<int, double>> vec;
    for (auto it : val) vec.push_back({it.first, it.second});
    sort(vec.begin(), vec.end(),
         [](auto a, auto b) { return a.second > b.second; });

    cout << t << "\n";
    for (int i = 0; i < t; i++) cout << vec[i].first << " ";
}

double maxn = -1;
int res = -1;
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> m[i] >> k[i];

    // 当1 < t <= 20时
    for (int t = 1; t <= 20; t++) {
        double sum = f(t);
        if (sum > maxn) maxn = sum, res = t;
    }

    // 预处理:排序,前缀和
    unordered_map<int, double> val;
    for (int i = 1; i <= n; i++) val[m[i]] += k[i];
    vector<pair<int, double>> vec;
    for (auto it : val) vec.push_back({it.first, it.second});
    sort(vec.begin(), vec.end(),
         [](auto a, auto b) { return a.second > b.second; });
    for (int i = 1; i < vec.size(); i++) vec[i].second += vec[i - 1].second;

    // 当t > 20时
    for (int t = 21; t <= vec.size(); t++) {
        double tmp = 1.0 * vec[t - 1].second / t;
        if (tmp > maxn) maxn = tmp, res = t;
    }

    print(res); // 输出结果

    return 0;
}