Educational Codeforces Round 120 Editorial E解题报告

Posted skywalker767

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 120 Editorial E解题报告相关的知识,希望对你有一定的参考价值。

传送门

学会了很多骚操作

题目描述


INPUT

3
4 3
5 1 2 2
110
100
101
100
4 4
6 2 0 10
1001
0010
0110
0101
3 6
20 3 15
010110
000101
111111

OUTPUT

3 1 2
2 3 4 1
3 1 4 5 2 6

题目大意: 给你 n n n个人每个人回答 m m m个题目,随后给 n n n个字符串,代表每一门有没有回答对。对于每个学生,老师有不同的期望值 x i x_i xi,每个人实际考 ∑ i m p i ∑_i^mp_i impi记为 r i r_i ri ∣ r i − x i ∣ |r_i - x_i| rixi是惊喜值,问,当 p i p_i pi这个全排列如何取时,惊喜值之和最大。
题解
m m m的范围比较大,直接枚举全排列会死的很惨。题目其实最后求的是
∑ i n ∣ x i − r i ∣ \\sum_i^n|x_i - r_i| inxiri
使其最大即可。我们可以枚举绝对值的每一个情况. Just x i − r i x_i - r_i xiri or r i − x i r_i - x_i rixi,最多有 2 n 2^n 2n种枚举方式。我们用二进制枚举。
∑ i n ∣ x i − r i ∣ = ∑ i n s i g n [ i ] r [ i ] − s i g n [ i ] x i \\sum_i^n|x_i - r_i| = \\sum_i^nsign[i]r[i]-sign[i]x_i inxiri=insign[i]r[i]sign[i]xi
后半部分在符号确定的时候是固定的,只需要前半部分最大即可。
∑ i n s i g n [ i ] r [ i ] = ∑ i n s i g n [ i ] ∑ j m p [ j ] ∗ a [ i ] [ j ] = ∑ j m p [ j ] ∑ i n s i g n [ i ] a [ i ] [ j ] \\sum_i^nsign[i]r[i] = \\sum_i^nsign[i]\\sum_j^mp[j]*a[i][j] = \\sum_j^mp[j]\\sum_i^nsign[i]a[i][j] insign[i]r[i]=insign[i]jmp[j]a[i][j]=jmp[j]insign[i]a[i][j]
∑ i n s i g n [ i ] a [ i ] [ j ] \\sum_i^nsign[i]a[i][j] insign[i]a[i][j]
记为: v a l [ j ] val[j] val[j]

答案为:
∑ j m p [ j ] ∗ v a l [ j ] \\sum_j^mp[j] * val[j] jmp[j]val[j]
源代码

#include <bits/stdc++.h>

#define forn(i, n) for (int i = 0; i < int(n); ++i)

using namespace std;

int main()

    int T; cin >> T;
    while (T --)
    
        int n , m;
        cin >> n >> m;
        vector<int> x(n);
        forn(i , n) cin >> x[i];
        vector<vector<int>> a(n , vector<int>(m));
        forn(i , n) forn(j , m) scanf("%1d" , &a[i][j]);
        
        int ans = -1;
        vector<int> best;
        forn(mask , 1 << n)
        
            vector<int> val(m);
            forn(i , n) forn(j , m) if (a[i][j]) val[j] += ((mask >> i) & 1) ? +1 : -1;
            int res = 0;
            forn(i , n) res += ((mask >> i) & 1) ? -x[i] : +x[i];
            vector<int> p(m);
            iota(p.begin() , p.end() , 0);
            sort(p.begin() , p.end() , [&](int a , int b) return val[a] < val[b];);
            forn(i , m) res += val[p[i]] * (i + 1);
            if (res > ans) ans = res , best = p;
        
        vector<int> ansR(m);
        forn(i , m) ansR[best[i]] = i;
        forn(i , m) printf("%d " , ansR[i] + 1);
        cout << endl;
    
    return 0;

参考:
https://zhuanlan.zhihu.com/p/450688661
https://codeforces.com/blog/entry/98453

以上是关于Educational Codeforces Round 120 Editorial E解题报告的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27