Educational Codeforces Round 177 (Rated for Div. 2)
A. Cloudberry Jam
题意:每个物品花费2的代价,问\(n\)个物品花费多少代价。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::cout << n * 2 << "\n";
}
B. Large Array and Segments
题意:把\(a\)复制\(k\)份,问有多少下标满足它的后缀和大于等于\(x\)。
这题二分会爆\(longlong\)然后\(WA \ test \ 4\)。
题目说了\(n, k\)总共不超过\(2e5\)。于是直接枚举过去,先一个数组一个数组的加,直到后缀和大于等于\(x\),然后一个一个数减,减到和小于\(x\)。
点击查看代码
void solve() {
int n, k;
i64 x;
std::cin >> n >> k >> x;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
i64 sum = std::accumulate(a.begin(), a.end(), 0ll);
int i = 0;
i64 s = 0;
for (; i < k && s < x; ++ i) {
s += sum;
}
int j = 0;
while (s >= x) {
s -= a[j];
++ j;
}
std::cout << (i64)n * k - ((i64)n * i - j) << "\n";
}
C. Disappearing Permutation
题意:给你一个排序\(p\),每次修改\(d_i\)这个位置为\(0\)。你每次可以选择一个\(i\)使得\(p_i = i\)。问每次修改后把数组恢复为一个排列的最小操作数。
如果修改了\(i\)这个位置为\(0\),那么我们需要操纵\(i\),那么此时\(p_i\)不存在了,我们需要操纵\(p_i\),同理操纵\(p_i\)后\(p_{p_i}\)又没有了,那么我们就一直使得\(i = p_i\), 一直跳到\(p_i\)本来就等于\(i\)的位置就可以停止操作了。
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> p(n);
for (int i = 0; i < n; ++ i) {
std::cin >> p[i];
-- p[i];
}
std::vector<int> d(n);
for (int i = 0; i < n; ++ i) {
std::cin >> d[i];
-- d[i];
}
std::vector<int> st(n);
int ans = 0;
for (int i = 0; i < n; ++ i) {
int x = d[i];
while (!st[x]) {
st[x] = 1;
++ ans;
x = p[x];
}
std::cout << ans << " \n"[i == n - 1];
}
}
D. Even String
题意:构造一个字符串是包含给定数量的字符,并且每个相等的字符要么同时在奇数位置上要么同时在偶数位置上,求方案数。
看起来貌似无从下手。
但我尝试暴力\(dp\)直接就够了。
记\(f[i][j]\)为奇数位置用了\(i\)个偶数位置用了\(j\)个方案数,那么对于一个有\(cnt\)数量的字符,可以转移到\(f[i + cnt][j] += C(odd - i, cnt) * f[i][j], f[i][j + cnt] += C(even - j) * f[i][j]\)。其中\(odd, even\)分别是奇数位置的总数和偶数位置的总数。然后答案是\(f[odd][even]\)。
代码省略取模类。
点击查看代码
struct Comb {
int n;
std::vector<Z> _fac;
std::vector<Z> _invfac;
std::vector<Z> _inv;
Comb() : n{0}, _fac{1}, _invfac{1}, _inv{0} {}
Comb(int n) : Comb() {
init(n);
}
void init(int m) {
if (m <= n) return;
_fac.resize(m + 1);
_invfac.resize(m + 1);
_inv.resize(m + 1);
for (int i = n + 1; i <= m; i++) {
_fac[i] = _fac[i - 1] * i;
}
_invfac[m] = _fac[m].inv();
for (int i = m; i > n; i--) {
_invfac[i - 1] = _invfac[i] * i;
_inv[i] = _invfac[i] * _fac[i - 1];
}
n = m;
}
Z fac(int m) {
if (m > n) init(2 * m);
return _fac[m];
}
Z invfac(int m) {
if (m > n) init(2 * m);
return _invfac[m];
}
Z inv(int m) {
if (m > n) init(2 * m);
return _inv[m];
}
Z binom(int n, int m) {
if (n < m || m < 0) return 0;
return fac(n) * invfac(m) * invfac(n - m);
}
} comb;
void solve() {
std::array<int, 26> cnt{};
for (int i = 0; i < 26; ++ i) {
std::cin >> cnt[i];
}
int m = std::accumulate(cnt.begin(), cnt.end(), 0);
int odd = (m + 1) / 2, even = m / 2;
std::map<std::pair<int, int>, Z> f;
f[{0, 0}] = 1;
for (int i = 0; i < 26; ++ i) {
if (!cnt[i]) {
continue;
}
std::map<std::pair<int, int>, Z> g;
for (auto & [it, v] : f) {
auto & [x, y] = it;
if (x + cnt[i] <= odd) {
g[{x + cnt[i], y}] += comb.binom(odd - x, cnt[i]) * v;
}
if (y + cnt[i] <= even) {
g[{x, y + cnt[i]}] += comb.binom(even - y, cnt[i]) * v;
}
}
f = g;
}
std::cout << f[{odd, even}] << "\n";
}