A. Two Screens
Problem Statement
There are two screens which can display sequences of uppercase Latin letters. Initially, both screens display nothing.
In one second, you can do one of the following two actions:
- choose a screen and an uppercase Latin letter, and append that letter to the end of the sequence displayed on that screen;
- choose a screen and copy the sequence from it to the other screen, overwriting the sequence that was displayed on the other screen.
You have to calculate the minimum number of seconds you have to spend so that the first screen displays the sequence s s s, and the second screen displays the sequence t t t.
Input
The first line contains one integer q q q ( 1 ≤ q ≤ 500 1 \le q \le 500 1≤q≤500) — the number of test cases.
Each test case consists of two lines. The first line contains the string s s s, and the second line contains the string t t t ( 1 ≤ ∣ s ∣ , ∣ t ∣ ≤ 100 1 \le |s|, |t| \le 100 1≤∣s∣,∣t∣≤100). Both strings consist of uppercase Latin letters.
Output
For each test case, print one integer — the minimum possible number of seconds you have to spend so that the first screen displays the sequence s s s, and the second screen displays the sequence t t t.
Example
input |
---|
3 |
GARAGE |
GARAGEFORSALE |
ABCDE |
AABCD |
TRAINING |
DRAINING |
output |
---|
14 |
10 |
16 |
Solution
具体见文后视频。
Code
#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
using namespace std;
typedef pair<int, int> PII;
void solve() {
string s, t;
cin >> s >> t;
if (s.size() > t.size()) swap(s, t);
int res = 0;
for (int i = 0; i < s.size(); i ++)
if (s[i] == t[i]) res ++;
else break;
cout << (int)s.size() + (int)t.size() - res + (res > 0) << endl;
}
signed main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int T;
cin >> T;
while (T -- ) solve();
return 0;
}
B. Binomial Coefficients, Kind Of
Problem Statement
Recently, akshiM met a task that needed binomial coefficients to solve. He wrote a code he usually does that looked like this:
for (int n = 0; n < N; n++) { // loop over n from 0 to N-1 (inclusive)
C[n][0] = 1;
C[n][n] = 1;
for (int k = 1; k < n; k++) // loop over k from 1 to n-1 (inclusive)
C[n][k] = C[n][k - 1] + C[n - 1][k - 1];
}
Unfortunately, he made an error, since the right formula is the following:
C[n][k] = C[n - 1][k] + C[n - 1][k - 1]
But his team member keblidA is interested in values that were produced using the wrong formula. Please help him to calculate these coefficients for t t t various pairs ( n i , k i ) (n_i, k_i) (ni,ki). Note that they should be calculated according to the first (wrong) formula.
Since values C [ n i ] [ k i ] C[n_i][k_i] C[ni][ki] may be too large, print them modulo 1 0 9 + 7 10^9 + 7 109+7.
Input
The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 5 1 \le t \le 10^5 1≤t≤105) — the number of pairs. Next, t t t pairs are written in two lines.
The second line contains t t t integers n 1 , n 2 , … , n t n_1, n_2, \dots, n_t n1,n2,…,nt ( 2 ≤ n i ≤ 1 0 5 2 \le n_i \le 10^5 2≤ni≤105).
The third line contains t t t integers k 1 , k 2 , … , k t k_1, k_2, \dots, k_t k1,k2,…,kt ( 1 ≤ k i < n i 1 \le k_i < n_i 1≤ki<ni).
Output
Print t t t integers C [ n i ] [ k i ] C[n_i][k_i] C[ni][ki] modulo 1 0 9 + 7 10^9 + 7 109+7.
Example
input |
---|
7 |
2 5 5 100000 100000 100000 100000 |
1 2 3 1 33333 66666 99999 |
output |
---|
2 |
4 |
8 |
2 |
326186014 |
984426998 |
303861760 |
Solution
具体见文后视频。
Code
#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
using namespace std;
typedef pair<int, int> PII;
signed main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
vector<int> pw(100005, 1);
for (int i = 1; i <= 100000; i ++) pw[i] = pw[i - 1] * 2 % 1000000007;
int n;
cin >> n;
int x;
for (int i = 1; i <= n; i ++) cin >> x;
for (int i = 1; i <= n; i ++) {
cin >> x;
cout << pw[x] << endl;
}
return 0;
}
C. New Game
Problem Statement
There’s a new game Monocarp wants to play. The game uses a deck of n n n cards, where the i i i-th card has exactly one integer a i a_i ai written on it.
At the beginning of the game, on the first turn, Monocarp can take any card from the deck. During each subsequent turn, Monocarp can take exactly one card that has either the same number as on the card taken on the previous turn or a number that is one greater than the number on the card taken on the previous turn.
In other words, if on the previous turn Monocarp took a card with the number x x x, then on the current turn he can take either a card with the number x x x or a card with the number x + 1 x + 1 x+1. Monocarp can take any card which meets that condition, regardless of its position in the deck.
After Monocarp takes a card on the current turn, it is removed from the deck.
According to the rules of the game, the number of distinct numbers written on the cards that Monocarp has taken must not exceed k k k.
If, after a turn, Monocarp cannot take a card without violating the described rules, the game ends.
Your task is to determine the maximum number of cards that Monocarp can take from the deck during the game, given that on the first turn he can take any card from the deck.
Input
The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104) — the number of test cases.
The first line of each test case contains two integers n n n and k k k ( 1 ≤ k ≤ n ≤ 200 000 1 \le k \le n \le 200\,000 1≤k≤n≤200000) — the number of cards in the deck and the maximum number of distinct numbers that can be written on the cards that Monocarp takes.
The second line contains a sequence of integers a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^{9} 1≤ai≤109), where a i a_i ai is the number written on the i i i-th card.
Additional constraint of the input: the sum of n n n over all test cases doesn’t exceed 200 000 200\,000 200000.
Output
For each test case, print the maximum number of cards that Monocarp can take from the deck during the game, given that on the first turn he can take any card from the deck.
Example
input |
---|
4 |
10 2 |
5 2 4 3 4 3 4 5 3 2 |
5 1 |
10 11 10 11 10 |
9 3 |
4 5 4 4 6 5 4 4 6 |
3 2 |
1 3 1 |
output |
---|
6 |
3 |
9 |
2 |
Solution
具体见文后视频。
Code
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define fi first
#define se second
using namespace std;
typedef pair<int, int> PII;
void solve() {
int n, m;
cin >> n >> m;
vector<int> a(n);
for (int i = 0; i < n; i ++) cin >> a[i];
sort(a.begin(), a.end());
int res = 0;
map<int, int> cnt;
for (int i = 0, j = 0; i < n; i ++) {
j = max(j, i);
if (!cnt.count(a[j])) cnt[a[j]] ++;
while (j + 1 < n && abs(a[j + 1] - a[j]) <= 1 && (cnt.size() < m || cnt.size() == m && a[j + 1] == a[j]))
j ++, cnt[a[j]] ++;
res = max(res, j - i + 1), cnt[a[i]] --;
if (cnt[a[i]] == 0) cnt.erase(a[i]);
}
cout << res << endl;
}
signed main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int T;
cin >> T;
while (T -- ) solve();
return 0;
}
D. Attribute Checks
Problem Statement
Imagine a game where you play as a character that has two attributes: “Strength” and “Intelligence”, that are at zero level initially.
During the game, you’ll acquire m m m attribute points that allow you to increase your attribute levels — one point will increase one of the attributes by one level. But sometimes, you’ll encounter a so-called “Attribute Checks”: if your corresponding attribute is high enough, you’ll pass it; otherwise, you’ll fail it.
Spending some time, you finally prepared a list which contains records of all points you got and all checks you’ve met. And now you’re wondering: what is the maximum number of attribute checks you can pass in a single run if you’d spend points wisely?
Note that you can’t change the order of records.
Input
The first line contains two integers n n n and m m m ( 1 ≤ m ≤ 5000 1 \le m \le 5000 1≤m≤5000; m < n ≤ 2 ⋅ 1 0 6 m < n \le 2 \cdot 10^6 m<n≤2⋅106) — the number of records in the list and the total number of points you’ll get during the game.
The second line contains n n n integers r 1 , r 2 , … , r n r_1, r_2, \dots, r_n r1,r2,…,rn ( − m ≤ r i ≤ m -m \le r_i \le m −m≤ri≤m), where r i r_i ri encodes the i i i-th record:
- If r i = 0 r_i = 0 ri=0, then the i i i-th record is an acquiring one attribute point. You can spend to level up either Strength or Intelligence;
- If r i > 0 r_i > 0 ri>0, then it’s an Intelligence check: if your Intelligence level is greater than or equal to ∣ r i ∣ |r_i| ∣ri∣, you pass.
- If r i < 0 r_i < 0 ri<0, then it’s a Strength check: if your Strength level is greater than or equal to ∣ r i ∣ |r_i| ∣ri∣, you pass.
Additional constraint on the input: the sequence r 1 , r 2 , … , r n r_1, r_2, \dots, r_n r1,r2,…,rn contains exactly m m m elements equal to 0 0 0.
Output
Print one integer — the maximum number of checks you can pass.
Example
input |
---|
10 5 |
0 1 0 2 0 -3 0 -4 0 -5 |
output |
---|
3 |
input |
---|
3 1 |
1 -1 0 |
output |
---|
0 |
input |
---|
9 3 |
0 0 1 0 2 -3 -2 -2 1 |
output |
---|
4 |
Solution
具体见文后视频。
Code
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define fi first
#define se second
using namespace std;
typedef pair<int, int> PII;
const int inf = 1E18;
signed main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int n, m;
cin >> n >> m;
vector<int> a(n), b;
vector<int> cnt(2 * m + 1, 0);
for (int i = 0; i < n; i ++) {
cin >> a[i];
if (a[i] == 0) b.push_back(i);
else cnt[a[i] + m] ++;
}
vector<vector<int>> dp(b.size(), vector<int>(m + 1, -inf));
int res = 0;
for (int i = 0; i < b.size(); i ++) {
for (int j = !i ? 0 : b[i - 1] + 1; j < b[i]; j ++) cnt[a[j] + m] --;
for (int j = 0; j <= m; j ++) {
dp[i][j] = (!i ? (j == 0 ? 0 : -inf) : dp[i - 1][j]) + cnt[m - (i - j + 1)];
if (j) dp[i][j] = max(dp[i][j], (!i ? (j == 1 ? 0 : -inf) : dp[i - 1][j - 1]) + cnt[j + m]);
res = max(res, dp[i][j]);
}
}
cout << res << endl;
return 0;
}
E. Card Game
Problem Statement
In the most popular card game in Berland, a deck of n × m n \times m n×m cards is used. Each card has two parameters: suit and rank. Suits in the game are numbered from 1 1 1 to n n n, and ranks are numbered from 1 1 1 to m m m. There is exactly one card in the deck for each combination of suit and rank.
A card with suit a a a and rank b b b can beat a card with suit c c c and rank d d d in one of two cases:
- a = 1 a = 1 a=1, c ≠ 1 c \ne 1 c=1 (a card of suit 1 1 1 can beat a card of any other suit);
- a = c a = c a=c, b > d b > d b>d (a card can beat any other card of the same suit but of a lower rank).
Two players play the game. Before the game starts, they receive exactly half of the deck each. The first player wins if for every card of the second player, he can choose his card that can beat it, and there is no card that is chosen twice (i. e. there exists a matching of the first player’s cards with the second player’s cards such that in each pair the first player’s card beats the second player’s card). Otherwise, the second player wins.
Your task is to calculate the number of ways to distribute the cards so that the first player wins. Two ways are considered different if there exists a card such that in one way it belongs to the first player and in the other way it belongs to the second player. The number of ways can be very large, so print it modulo 998244353 998244353 998244353.
Input
The only line contains two integers n n n and m m m ( 1 ≤ n , m ≤ 500 1 \le n, m \le 500 1≤n,m≤500).
Additional constraint on the input: m m m is even.
Output
Print a single integer — the number of ways to distribute the cards so that the first player wins, taken modulo 998244353 998244353 998244353.
Example
input |
---|
1 4 |
output |
---|
2 |
input |
---|
2 2 |
output |
---|
2 |
input |
---|
3 6 |
output |
---|
1690 |
input |
---|
5 4 |
output |
---|
568 |
input |
---|
500 500 |
output |
---|
84693741 |
Solution
具体见文后视频。
Code
#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
using namespace std;
const int N = 5E2 + 10, mod = 998244353;
int n, m;
int dp[N][N], C[N][N], f[N][N];
int ksm(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
signed main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
for (int i = 0; i < N; i ++)
for (int j = 0; j <= i; j ++)
if (!j) C[i][j] = 1;
else C[i][j] = C[i - 1][j] + C[i - 1][j - 1], C[i][j] %= mod;
cin >> n >> m;
f[0][0] = 1;
for (int i = 1; i <= m; i ++)
for (int j = 0; j <= m; j ++) {
if (j) f[i][j] += f[i - 1][j - 1];
if (j < m) f[i][j] += f[i - 1][j + 1];
f[i][j] %= mod;
}
for (int i = 0; i <= m; i += 2) dp[1][i] = f[m][i];
for (int i = 2; i <= n; i ++)
for (int j = 0; j <= m; j ++)
for (int k = 0; k <= j; k += 2)
dp[i][j - k] += dp[i - 1][j] * f[m][k] % mod, dp[i][j - k] %= mod;
cout << dp[n][0] << endl;
return 0;
}
F. Choose Your Queries
Problem Statement
You are given an array a a a, consisting of n n n integers (numbered from 1 1 1 to n n n). Initially, they are all zeroes.
You have to process q q q queries. The i i i-th query consists of two different integers x i x_i xi and y i y_i yi. During the i i i-th query, you have to choose an integer p p p (which is either x i x_i xi or y i y_i yi) and an integer d d d (which is either 1 1 1 or − 1 -1 −1), and assign a p = a p + d a_p = a_p + d ap=ap+d.
After each query, every element of a a a should be a non-negative integer.
Process all queries in such a way that the sum of all elements of a a a after the last query is the minimum possible.
Input
The first line contains two integers n n n and q q q ( 2 ≤ n ≤ 3 ⋅ 1 0 5 2 \le n \le 3 \cdot 10^5 2≤n≤3⋅105; 1 ≤ q ≤ 3 ⋅ 1 0 5 1 \le q \le 3 \cdot 10^5 1≤q≤3⋅105) — the number of elements in a a a and the number of queries, respectively.
Then q q q lines follow. The i i i-th of these lines contains two integers x i x_i xi and y i y_i yi ( 1 ≤ x i , y i ≤ n 1 \le x_i, y_i \le n 1≤xi,yi≤n; x i ≠ y i x_i \ne y_i xi=yi) — the description of the i i i-th query.
Output
For each query, print a line containing two characters:
- the first character should be x if you choose p = x i p=x_i p=xi, or y if you choose p = y i p=y_i p=yi;
- the second character should be + if you choose d = 1 d=1 d=1, or - if you choose d = − 1 d=-1 d=−1.
If there are multiple answers, print any of them.
Example
input |
---|
3 4 |
1 2 |
3 2 |
3 1 |
1 2 |
output |
---|
y+ |
x+ |
x- |
y- |
input |
---|
4 4 |
1 2 |
2 3 |
3 4 |
3 2 |
output |
---|
y+ |
y+ |
x- |
y- |
input |
---|
4 2 |
2 1 |
4 3 |
output |
---|
y+ |
x+ |
Solution
具体见文后视频。
Code
#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
using namespace std;
typedef pair<int, int> PII;
const int N = 3E5 + 10;
int n, q;
vector<PII> g[N], edge;
bool st[N], vis[N], res[N];
void dfs(int u) {
vis[u] = 1;
for (auto v : g[u]) {
if (vis[v.fi]) continue;
dfs(v.fi);
st[u] ^= st[v.fi], res[v.se] = st[v.fi];
}
}
signed main() {
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
cin >> n >> q;
for (int i = 1; i <= q; i ++) {
int u, v;
cin >> u >> v, st[u] ^= 1, edge.push_back({u, v});
g[u].push_back({v, i}), g[v].push_back({u, i});
}
for (int i = 1; i <= n; i ++) if (!vis[i]) dfs(i);
memset(st, 0, sizeof st);
for (int i = 1; i <= q; i ++) {
if (res[i]) {
st[edge[i - 1].se] ^= 1;
if (st[edge[i - 1].se]) cout << "y+";
else cout << "y-";
} else {
st[edge[i - 1].fi] ^= 1;
if (st[edge[i - 1].fi]) cout << "x+";
else cout << "x-";
}
cout << endl;
}
return 0;
}
视频讲解
Educational Codeforces Round 170 (Rated for Div. 2)(A ~ F 题讲解)
最后祝大家早日