组合题5 个小题
已作答 0 / 5
给定 n 名学生参加一场考试,考试共有 m 道选择题,每道题只有 A、B 两个选项。
第 i 名学生的作答为一个长度为 m 的字符串。若最终公布的标准答案与该学生在某道题上的作答相同,则该学生在这道题上得 1 分,否则不得分。记第 i 名学生最终得到的总分为 ri。
每名学生还有一个预期得分 xi。现在需要构造一份标准答案,使
尽可能大。
数据满足 1≤n≤18,1≤m≤300,0≤xi≤m。
提示:可以换一个角度处理 ∑i=1n∣ri−xi∣,把它写成更易优化的形式;对正整数 x,__builtin_ctzll(x) 返回 x 的二进制表示末尾连续 0 的个数;__builtin_popcountll(x) 返回 x 的二进制表示中 1 的个数。
以下程序构造出一组满足要求的标准答案。请补全程序。
1#include <cstdlib>2#include <iostream>3#include <string>4#include <vector>5using namespace std;6typedef long long ll;7typedef unsigned long long ull;8int main() {9 int n, m;10 cin >> n >> m;11 vector<ll> x(n), c(n);12 for (int i = 0; i < n; i++) {13 cin >> x[i];14 c[i] = /* ① */;15 }16 vector<string> a(n);17 for (int i = 0; i < n; i++)18 cin >> a[i];19 vector<int> s(n, -1);20 vector<ll> q(m, 0);21 ll C = 0, S = 0;22 for (int i = 0; i < n; i++) {23 C -= c[i];24 for (int j = 0; j < m; j++) {25 if (a[i][j] == 'A') q[j]--;26 else q[j]++;27 }28 }29 for (int j = 0; j < m; j++) S += abs(q[j]);30 ll ans = C + S;31 ull best = 0, lst = 0;32 for (ull mask = 1; mask < (1ULL << n); mask++) {33 ull g = /* ② */;34 ull d = g ^ lst;35 int k = /* ③ */;36 C -= /* ④ */;37 for (int j = 0; j < m; j++) {38 ll old = q[j];39 int v = (a[k][j] == 'A' ? 1 : -1);40 q[j] -= 2ll * s[k] * v;41 S += abs(q[j]) - abs(old);42 }43 s[k] = -s[k];44 if (C + S > ans) {45 ans = C + S;46 best = g;47 }48 lst = g;49 }50 for (int i = 0; i < n; i++) {51 if ((best >> i) & 1) s[i] = 1;52 else s[i] = -1;53 }54 string res(m, 'A');55 for (int j = 0; j < m; j++) {56 ll v = 0;57 for (int i = 0; i < n; i++) {58 if (a[i][j] == 'A') v += s[i];59 else v -= s[i];60 }61 if (/* ⑤ */) res[j] = 'A';62 else res[j] = 'B';63 }64 cout << res << endl;65 return 0;66}②处应填( )。