AtCoder Beginner Contest 405
A - Is it rated?
点击查看代码
void solve() {
int R, x;
std::cin >> R >> x;
int l = 1600, r = 2999;
if (x == 2) {
l = 1200, r = 2399;
}
if (R >= l && R <= r) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
B - Not All
题意:判断删除最短的一个后缀,使得剩下的数不同时包含\([1, m]\)的每个数。
用\(set\)从前往后记录,如果个数等于\(m\)那么后面的都要删掉。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int ans = 0;
std::set<int> s;
for (int i = 0; i < n; ++ i) {
s.insert(a[i]);
if (s.size() == m) {
ans = n - i;
break;
}
}
std::cout << ans << "\n";
}
C - Sum of Product
题意:给你\(a\)数组,求\(\sum_{i=1}^{n} \sum_{j=i+1}^{n} a_i\times a_j\)。
经典结论,答案为\((\sum_{i=1}^{n} a_i)^2 - \sum_{i=1}^{n} a_i^2\)。
点击查看代码
void solve() {
int n;
std::cin >> n;
i64 ans = 0, sum = 0;
for (int i = 0; i < n; ++ i) {
i64 x;
std::cin >> x;
sum += x;
ans -= x * x;
}
ans += sum * sum;
std::cout << ans / 2 << "\n";
}
D - Escape Route
题意:大意是有一些出口,你要给每个空地标记方向。使得一直往格子标记的方向走可以到一个距离最近的出口。
多源最短路,一开始把所有出口入队。然后\(bfs\)就行,记录一些每个方向对应要填的符号。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::string> s(n);
for (int i = 0; i < n; ++ i) {
std::cin >> s[i];
}
std::vector st(n, std::vector<int>(m));
std::queue<std::pair<int, int>> q;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
if (s[i][j] == 'E') {
q.emplace(i, j);
st[i][j] = 1;
}
}
}
const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
std::string ch = "v<^>";
while (q.size()) {
auto [x, y] = q.front(); q.pop();
for (int i = 0; i < 4; ++ i) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m || s[nx][ny] == '#' || st[nx][ny]) {
continue;
}
s[nx][ny] = ch[i];
st[nx][ny] = 1;
q.emplace(nx, ny);
}
}
for (int i = 0; i < n; ++ i) {
std::cout << s[i] << "\n";
}
}
E - Fruit Lineup
题意:苹果、橘子、香蕉、葡萄分别有\(A, B, C, D\)个。把他们排成一排,苹果不能放在香蕉和葡萄后面,橘子不能放在葡萄后面。求不同的组合数。
把它们分成两部分,枚举前部分放了多少个香蕉。
如果前部分放了\(k\)个香蕉,那么后面的方案数容易得出,因为后面只能放剩下的香蕉和葡萄,而它们没有限制,后面的答案是\(C(C - k + D, D)\)。前部分的方案可以先把苹果和香蕉排成一排,因为相同水果没有区间,所以只有一种方案。那么接下来需要用\(B\)个橘子插在里面,每个间隙可以插任意个,那么就是经典插板法,方案数为\(C(A + B + k - 1, B - 1)\)。所以答案为\(C(A + B + k - 1, B - 1) \times C(C - k + D, D)\)。
注意特判\(k=0\)的情况。
代码省略取模类。
点击查看代码
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() {
int a, b, c, d;
std::cin >> a >> b >> c >> d;
int n = a + b + c + d;
Z ans = comb.binom(a + b, a) * comb.binom(c + d, d);
for (int k = 1; k <= c; ++ k) {
ans += comb.binom(a + b + k - 1, b - 1) * comb.binom(c - k + d, d);
}
std::cout << ans << "\n";
}
F - Chord Crossing
题意:\(2n\)排成一个圆。有\(m\)条边连接编号为偶数的点。每次询问如果在两个奇数的点加边,会和多少边相交。
其实就是求\([l, r]\)里有多少点往外有边。我们用主席树维护,每个点把所有出边所有的点的位置加一就行,然后询问第\([l, r]\)这些树有多少在区间外面的点。
点击查看代码
#define ls(u) tr[u].lson
#define rs(u) tr[u].rson
const int N = 2e6 + 5;
struct Node {
int lson, rson;
int sum;
}tr[N << 5];
int root[N], tot;
void build(int &u, int l, int r) {
u = ++ tot;
if (l == r) {
return;
}
int mid = l + r >> 1;
build(ls(u), l, mid); build(rs(u), mid + 1, r);
}
void modify(int & u, int v, int L, int R, int p, int add) {
u = ++ tot;
tr[u] = tr[v];
tr[u].sum += add;
if (L == R) {
return;
}
int mid = L + R >> 1;
if (p <= mid) {
modify(ls(u), ls(v), L, mid, p, add);
}
if (p > mid) {
modify(rs(u), rs(v), mid + 1, R, p, add);
}
}
int query(int u, int v, int L, int R, int l, int r) {
if (l <= L && R <= r) {
return tr[u].sum - tr[v].sum;
}
int mid = L + R >> 1;
if (r <= mid) {
return query(ls(u), ls(v), L, mid, l, r);
} else if (l > mid) {
return query(rs(u), rs(v), mid + 1, R, l, r);
}
return query(ls(u), ls(v), L, mid, l, mid) + query(rs(u), rs(v), mid + 1, R, mid + 1, r);
}
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::vector<int>> adj(2 * n + 1);
for (int i = 0; i < m; ++ i) {
int u, v;
std::cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
for (int i = 1; i <= 2 * n; ++ i) {
root[i] = root[i - 1];
for (auto & v : adj[i]) {
modify(root[i], root[i], 1, 2 * n, v, 1);
}
}
int q;
std::cin >> q;
while (q -- ) {
int l, r;
std::cin >> l >> r;
std::cout << query(root[r], root[l], 1, 2 * n, 1, l) + query(root[r], root[l], 1, 2 * n, r, 2 * n) << "\n";
}
}

浙公网安备 33010602011771号