A. Even Substrings
Description:
You are given a string of length , which only contains digits , , …, .
A substring of is a string . A substring of is called even if the number represented by it is even.
Find the number of even substrings of . Note, that even if some substrings are equal as strings, but have different and , they are counted as different substrings.
Input:
The first line contains an integer () — the length of the string .
The second line contains a string of length . The string consists only of digits , , …, .
Output
Print the number of even substrings of .
Sample Input:
4
1234
Sample Output:
6
Sample Input:
4
2244
Sample Output:
10
题目链接
求偶数子串数量
对每位是偶数地数求和即可
AC代码:
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0); std::cout.tie(0);
long long n; std::cin >> n;
std::string str; std::cin >> str;
long long ans = 0;
for (long long i = 0; i < n; ++i) {
if ((str[i] - '0') % 2 == 0) ans += i + 1;
}
std::cout << ans << '\n';
return 0;
}
B. Chocolates
Description:
You went to the store, selling types of chocolates. There are chocolates of type in stock.
You have unlimited amount of cash (so you are not restricted by any prices) and want to buy as many chocolates as possible. However if you buy chocolates of type (clearly, ), then for all at least one of the following must hold:
- (you bought zero chocolates of type )
- (you bought less chocolates of type than of type )
For example, the array satisfies the requirement above (assuming that all ), while arrays , and don’t.
Calculate the maximum number of chocolates you can buy.
Input:
The first line contains an integer (), denoting the number of types of chocolate.
The next line contains integers (), denoting the number of chocolates of each type.
Output
Print the maximum number of chocolates you can buy.
Sample Input:
5
1 2 1 3 6
Sample Output:
10
Sample Input:
5
3 2 5 4 10
Sample Output:
20
Sample Input:
4
1 1 1 1
Sample Output:
1
题目链接
求每个元素不超过上限的严格上升序列最大和
倒推每位都去可能的最大值即可
AC代码:
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0); std::cout.tie(0);
long long n; std::cin >> n;
std::vector<long long> a(n);
for (auto &it : a) std::cin >> it;
std::vector<long long> b(n);
b[n - 1] = a[n - 1];
long long ans = b[n - 1];
for (int i = n - 2; i >= 0; --i) {
b[i] = std::max((long long)0, std::min(a[i], b[i + 1] - 1ll));
ans += b[i];
}
std::cout << ans << '\n';
return 0;
}
C. Edgy Trees
Description:
You are given a tree (a connected undirected graph without cycles) of vertices. Each of the edges of the tree is colored in either black or red.
You are also given an integer . Consider sequences of vertices. Let’s call a sequence good if it satisfies the following criterion:
We will walk a path (possibly visiting same edge/vertex multiple times) on the tree, starting from and ending at . Start at , then go to using the shortest path between and , then go to in a similar way, and so on, until you travel the shortest path between and . If you walked over at least one black edge during this process, then the sequence is good. Consider the tree on the picture. If then the following sequences are good: , and . The following sequences are not good: , , .
There are sequences of vertices, count how many of them are good. Since this number can be quite large, print it modulo .
Input:
The first line contains two integers and (, ), the size of the tree and the length of the vertex sequence.
Each of the next lines contains three integers , and (, ), where and denote the endpoints of the corresponding edge and is the color of this edge ( denotes red edge and denotes black edge).
Output
Print the number of good sequences modulo .
Sample Input:
4 4
1 2 1
2 3 1
3 4 1
Sample Output:
252
Sample Input:
4 6
1 2 0
1 3 0
1 4 0
Sample Output:
0
Sample Input:
3 5
1 2 1
2 3 0
Sample Output:
210
题目链接
一棵树上的边有红色的黑色之分,求包含 个节点且至少经过一次黑边的路径数
总路径方案数就是 ,考虑将树上黑边删除只保留红边,求出每个连通块的节点数 x,这样对每个连通块会有 种方案不合法,在总数中减去即可
AC代码:
#include <bits/stdc++.h>
const long long mod = 1e9 + 7;
long long QuickPow(long long k, long long n) {
if (n == 0) return 1;
long long ans = 1;
while (n) {
if (n & 1) ans = ans * k % mod;
k = k * k % mod;
n >>= 1;
}
return ans;
}
long long n, k;
std::vector<std::vector<int>> g;
std::vector<bool> vis;
int Dfs(int cur) {
vis[cur] = true;
int cnt = 1;
for (auto &it : g[cur]) {
if (vis[it]) continue;
cnt += Dfs(it);
}
return cnt;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0); std::cout.tie(0);
std::cin >> n >> k;
g.resize(n); vis.assign(n, false);
for (int i = 1, u, v, x; i < n; ++i) {
std::cin >> u >> v >> x;
--u; --v;
if (x == 0) {
g[u].emplace_back(v);
g[v].emplace_back(u);
}
}
long long ans = QuickPow(n, k);
for (int i = 0; i < n; ++i) {
if (!vis[i])
ans = (ans - QuickPow(Dfs(i), k) + mod) % mod;
}
std::cout << ans << '\n';
return 0;
}
E. Maximize Mex
Description:
There are students and clubs in a college. The clubs are numbered from to . Each student has a potential and is a member of the club with index . Initially, each student is a member of exactly one club. A technical fest starts in the college, and it will run for the next days. There is a coding competition every day in the technical fest.
Every day, in the morning, exactly one student of the college leaves their club. Once a student leaves their club, they will never join any club again. Every day, in the afternoon, the director of the college will select one student from each club (in case some club has no members, nobody is selected from that club) to form a team for this day’s coding competition. The strength of a team is the mex of potentials of the students in the team. The director wants to know the maximum possible strength of the team for each of the coming days. Thus, every day the director chooses such team, that the team strength is maximized.
The mex of the multiset is the smallest non-negative integer that is not present in . For example, the mex of the is , the mex of is and the mex of (empty set) is .
Input:
The first line contains two integers and (), the number of students and the number of clubs in college.
The second line contains integers (), where is the potential of the -th student.
The third line contains integers (), which means that -th student is initially a member of the club with index .
The fourth line contains an integer (), number of days for which the director wants to know the maximum possible strength of the team.
Each of the next lines contains an integer (), which means that -th student lefts their club on the -th day. It is guaranteed, that the -th student has not left their club earlier.
Output
For each of the days, print the maximum possible strength of the team on that day.
Sample Input:
5 3
0 1 2 2 0
1 2 2 3 2
5
3
2
4
5
1
Sample Output:
3
1
1
1
0
Sample Input:
5 3
0 1 2 2 1
1 3 2 3 2
5
4
2
3
5
1
Sample Output:
3
2
2
1
0
Sample Input:
5 5
0 1 2 4 5
1 2 3 4 5
4
2
3
5
4
Sample Output:
1
1
1
1
题目链接
每个人有一个权值 ,每个人又归属于一个集合 , 次操作每次删除一个人,之后求出每个集合选一个人组成集合的最小非负数的最大值
考虑把操作离线并反转,将集合与每个人的权值建图,每次添加人(加边)跑最大流(二分图匹配)即可
AC代码:
#include <bits/stdc++.h>
namespace NetFlow {
const int inf = 0x3f3f3f3f;
int s, t;
struct edge {int to, cap, rev;};
std::vector<std::vector<edge>> g;
std::vector<bool> vis;
void Init(int n) {
s = 0; t = n;
g.resize(n + 1);
}
void AddEdge(int u, int v, int cap, int rev = 0) {
g[u].push_back((edge){v, cap, (int)g[v].size()});
g[v].push_back((edge){u, rev, (int)g[u].size() - 1});
}
int Dfs(int u, int t, int flow) {
if (u == t) return flow;
vis[u] = true;
for (edge &e : g[u]) {
if (!vis[e.to] && e.cap > 0) {
int f = Dfs(e.to, t, std::min(e.cap, flow));
if (f > 0) {
e.cap -= f;
g[e.to][e.rev].cap += f;
return f;
}
}
}
return 0;
}
int GetMaxFlow(int s, int t) {
int ans = 0;
while (true) {
vis.assign(t + 1, false);
int flow = Dfs(s, t, inf);
if (flow == 0) return ans;
ans += flow;
}
}
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0); std::cout.tie(0);
int n, m; std::cin >> n >> m;
std::vector<int> p(n, 0), c(n, 0);
std::vector<std::vector<int>> cnt(5005);
for (int i = 0; i < n; ++i) std::cin >> p[i];
for (int i = 0; i < n; ++i) {
std::cin >> c[i];
--c[i];
}
int d; std::cin >> d;
std::vector<int> q(d);
std::vector<bool> del(n, false);
for (int i = 0; i < d; ++i) {
std::cin >> q[i];
--q[i];
del[q[i]] = true;
}
int s = m + 5005, t = s + 1;
NetFlow::Init(t);
for (int i = 0; i < m; ++i) NetFlow::AddEdge(s, i, 1);
for (int i = 0; i < n; ++i)
if (!del[i]) NetFlow::AddEdge(c[i], m + p[i], 1);
std::vector<int> ans(d);
int cur_mx = -1, cur_match = 0;
for (int i = d - 1; i >= 0; --i) {
while (cur_mx < 5001 && cur_match == cur_mx + 1) {
++cur_mx;
NetFlow::AddEdge(m + cur_mx, t, 1);
cur_match += NetFlow::GetMaxFlow(s, t);
}
ans[i] = cur_mx;
NetFlow::AddEdge(c[q[i]], m + p[q[i]], 1);
cur_match += NetFlow::GetMaxFlow(s, t);
}
for (int i = 0; i < d; ++i) std::cout << ans[i] << '\n';
return 0;
}