ll minodd = inf; // inf > sum of all elements ll sum = 0; while (l--) { int x; cin >> x; if (x & 1) { minodd = min<ll>(minodd, x); } sum += x; } ll sum2 = sum - minodd; // When there are no odd numbers, sum2 < 0 vector<vector<int>> E(2 * n); auto add = [&](int u, int v) { E[u].push_back(v); E[v].push_back(u); }; while (m--) { int u, v; cin >> u >> v; u--; v--; add(u, v + n); add(u + n, v); }
// BFS vector<int> dis(2 * n, -1); dis[0] = 0; queue<int> Q; Q.push(0); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (auto& v : E[u]) { if (dis[v] != -1) continue; dis[v] = dis[u] + 1; Q.push(v); } }
string res(n, '0'); for (int i = 0; i < 2 * n; i++) { if (dis[i] == -1) continue; if (dis[i] % 2 == sum % 2) { if (dis[i] <= sum) { res[i % n] = '1'; } } else { if (dis[i] <= sum2) { res[i % n] = '1'; } } } cout << res << endl; }
第 i 位的操作次数只与后缀有关,考虑倒着 DP,设 dpi,j 表示对 i 的后缀操作 j 次的方案数。
考虑转移 dpi,j←dpi−1,k,即第 i 位处操作 j−k 次的方案数。每次操作,第 i 位都会翻转。如果 si=0,只能是总共操作偶数次后才能操作第 i 位。也就是说对于这个 j 长的操作序列,操作第 i 位只能放在第奇数位置上,方案数是 (j−k⌈2j⌉)。如果 si=1,就只能放在第偶数位置上,方案数是 (j−k⌊2j⌋)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
int N, K; string S; cin >> N >> K >> S;
vector<Z> f(K + 1); f[0] = 1; for (int i = N - 1; i >= 0; i--) { vector<Z> nf(K + 1); for (int j = 0; j <= K; j++) { for (int k = 0; k <= j; k++) { nf[j] += f[k] * binom((j + (S[i] == '0')) / 2, j - k); } } f = nf; } cout << f[K] << endl;