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|
∣ri−xi∣是惊喜值,问,当
p
i
p_i
pi这个全排列如何取时,惊喜值之和最大。
题解
m
m
m的范围比较大,直接枚举全排列会死的很惨。题目其实最后求的是
∑
i
n
∣
x
i
−
r
i
∣
\\sum_i^n|x_i - r_i|
i∑n∣xi−ri∣
使其最大即可。我们可以枚举绝对值的每一个情况. Just
x
i
−
r
i
x_i - r_i
xi−ri or
r
i
−
x
i
r_i - x_i
ri−xi,最多有
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
i∑n∣xi−ri∣=i∑nsign[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]
i∑nsign[i]r[i]=i∑nsign[i]j∑mp[j]∗a[i][j]=j∑mp[j]i∑nsign[i]a[i][j]
∑
i
n
s
i
g
n
[
i
]
a
[
i
]
[
j
]
\\sum_i^nsign[i]a[i][j]
i∑nsign[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]
j∑mp[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