2145A - Конфеты для племянников
Идея: fcspartakm
Разбор
Tutorial is loading...
Решение (fcspartakm)
#include <iostream>
using namespace std;
int main() {
int t;
cin >> t;
for(int i = 0; i < t; i++)
{
int n;
cin >> n;
cout << (3 - n % 3) % 3 << endl;
}
}
Идея: BledDest
Разбор
Tutorial is loading...
Решение (Neon)
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
string s;
cin >> n >> k >> s;
int a = count(s.begin(), s.end(), '0');
int b = count(s.begin(), s.end(), '1');
int c = count(s.begin(), s.end(), '2');
string ans(n, '+');
for (int i = 0; i < n; ++i) {
if (i < a + c || i >= n - b - c) ans[i] = '?';
if (i < a || i >= n - b || k == n) ans[i] = '-';
}
cout << ans << '\n';
}
}
Идея: fcspartakm
Разбор
Tutorial is loading...
Решение (BledDest)
#include <bits/stdc++.h>
using namespace std;
#define forn(i, n) for(int i = 0; i < int(n); i++)
void solve() {
int n;
string s;
cin >> n >> s;
int cur = count(s.begin(), s.end(), 'a') - count(s.begin(), s.end(), 'b');
map<int, int> lst;
int pr = 0;
lst[pr] = -1;
int ans = n;
forn(i, n){
pr += s[i] == 'a' ? 1 : -1;
lst[pr] = i;
if (lst.count(pr - cur))
ans = min(ans, i - lst[pr - cur]);
}
cout << (ans == n ? -1 : ans) << '\n';
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
forn(i, t) solve();
}
2145D - Инверсионность перестановки
Идея: BledDest
Разбор
Tutorial is loading...
Решение (BledDest)
t = int(input())
for i in range(t):
n, k = map(int, input().split())
maxk = n * (n - 1) // 2
dp = [[False for i in range(maxk + 1)] for j in range(n + 1)]
p = [[-1 for i in range(maxk + 1)] for j in range(n + 1)]
dp[0][0] = True
for j in range(n):
for x in range(maxk + 1):
for y in range(1, n - j + 1):
if not dp[j][x]:
continue
add = y * (y - 1) // 2
dp[j + y][x + add] = True
p[j + y][x + add] = y
k = maxk - k
if dp[n][k]:
ans = []
cur = n
curk = k
while cur != 0:
y = p[cur][curk]
ans.append(y)
curk -= y * (y - 1) // 2
cur -= y
res = []
cur = n + 1
for y in ans:
for x in range(cur - y, cur):
res.append(x)
cur -= y
print(*res)
else:
print(0)
2145E - Прогнозирование популярности
Идея: adedalic
Разбор
Tutorial is loading...
Решение (adedalic)
#include<bits/stdc++.h>
using namespace std;
#define fore(i, l, r) for(int i = int(l); i < int(r); i++)
#define sz(a) int((a).size())
#define x first
#define y second
typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;
template<class A, class B> ostream& operator <<(ostream& out, const pair<A, B> &p) {
return out << "(" << p.x << ", " << p.y << ")";
}
template<class A> ostream& operator <<(ostream& out, const vector<A> &v) {
fore(i, 0, sz(v)) {
if(i) out << " ";
out << v[i];
}
return out;
}
const int INF = int(1e9);
const li INF64 = li(1e18);
const ld EPS = 1e-9;
int ac, dr;
int n;
vector<int> a, d;
inline bool read() {
if(!(cin >> ac >> dr))
return false;
cin >> n;
a.resize(n);
fore (i, 0, n)
cin >> a[i];
d.resize(n);
fore (i, 0, n)
cin >> d[i];
return true;
}
vector<int> Tadd, Tmin;
void push(int v) {
Tadd[2 * v + 1] += Tadd[v];
Tadd[2 * v + 2] += Tadd[v];
Tadd[v] = 0;
}
int getmin(int v) {
return Tmin[v] + Tadd[v];
}
void upd(int v) {
Tmin[v] = min(getmin(2 * v + 1), getmin(2 * v + 2));
}
void init(int v, int l, int r) {
if (l + 1 == r) {
Tmin[v] = -l;
return;
}
int mid = (l + r) >> 1;
init(2 * v + 1, l, mid);
init(2 * v + 2, mid, r);
upd(v);
}
void init(int n) {
Tadd.assign(4 * n, 0);
Tmin.resize(4 * n);
init(0, 0, n);
}
void addVal(int v, int l, int r, int lf, int rg, int val) {
if (l == lf && r == rg) {
Tadd[v] += val;
return;
}
int mid = (l + r) >> 1;
push(v);
if (lf < mid)
addVal(2 * v + 1, l, mid, lf, min(mid, rg), val);
if (rg > mid)
addVal(2 * v + 2, mid, r, max(lf, mid), rg, val);
upd(v);
}
int firstNeg(int v, int l, int r) {
if (l + 1 == r) {
assert(getmin(v) < 0);
return l;
}
push(v);
int mid = (l + r) >> 1;
int ans = -1;
if (getmin(2 * v + 1) < 0)
ans = firstNeg(2 * v + 1, l, mid);
else
ans = firstNeg(2 * v + 2, mid, r);
upd(v);
return ans;
}
int calcDemand(int i) {
return min(n, max(a[i] - ac, 0) + max(d[i] - dr, 0));
}
inline void solve() {
init(n + 2);
fore (i, 0, n) {
int p = calcDemand(i);
addVal(0, 0, n + 2, p + 1, n + 2, 1);
}
int m; cin >> m;
fore (j, 0, m) {
int k, na, nd;
cin >> k >> na >> nd;
k--;
int p = calcDemand(k);
addVal(0, 0, n + 2, p + 1, n + 2, -1);
a[k] = na;
d[k] = nd;
p = calcDemand(k);
addVal(0, 0, n + 2, p + 1, n + 2, 1);
int ans = firstNeg(0, 0, n + 2);
cout << ans - 1 << '\n';
}
}
int main() {
#ifdef _DEBUG
freopen("input.txt", "r", stdin);
int tt = clock();
#endif
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cout << fixed << setprecision(15);
if(read()) {
solve();
#ifdef _DEBUG
cerr << "TIME = " << clock() - tt << endl;
tt = clock();
#endif
}
return 0;
}
Идея: BledDest
Разбор
Tutorial is loading...
Решение (Neon)
#include <bits/stdc++.h>
using namespace std;
using li = long long;
const int N = 10;
const int LOG = 50;
const int LCM = 2520;
int n;
li m;
int a[N], b[N];
li go[LOG][N][LCM];
void solve() {
cin >> n >> m;
for (int i = 0; i < n; ++i) cin >> a[i];
for (int i = 0; i < n; ++i) cin >> b[i];
for (int x = 0; x < n; ++x) {
for (int y = 0; y < LCM; ++y) {
go[0][x][y] = ((y + 1) % a[x]) != b[x];
}
}
for (int i = 1; i < LOG; ++i) {
for (int x = 0; x < n; ++x) {
for (int y = 0; y < LCM; ++y) {
go[i][x][y] = go[i - 1][x][y] + go[i - 1][(x + (1LL << (i - 1))) % n][(y + go[i - 1][x][y]) % LCM];
}
}
}
if (go[LOG - 1][0][0] < m) {
cout << -1 << endl;
return;
}
li s = 0, ans = 0;
for (int i = LOG - 1; i >= 0; --i) {
if (s + go[i][ans % n][s % LCM] < m) {
s += go[i][ans % n][s % LCM];
ans += 1LL << i;
}
}
cout << ans + 1 << endl;
}
int main() {
int t;
cin >> t;
while (t--) solve();
}
Идея: BledDest
Разбор
Tutorial is loading...
Решение (BledDest)
#include<bits/stdc++.h>
using namespace std;
int n, m, k;
const int N = 4043;
const int MOD = 998244353;
int add(int x, int y)
{
x += y;
while(x >= MOD) x -= MOD;
while(x < 0) x += MOD;
return x;
}
int sub(int x, int y)
{
return add(x, -y);
}
int mul(int x, int y)
{
return (x * 1ll * y) % MOD;
}
int binpow(int x, int y)
{
int z = 1;
while(y > 0)
{
if(y % 2 == 1) z = mul(z, x);
x = mul(x, x);
y /= 2;
}
return z;
}
int fact[N];
int rfact[N];
void precalc_factorials()
{
fact[0] = 1;
for(int i = 1; i < N; i++)
fact[i] = mul(fact[i - 1], i);
for(int i = 0; i < N; i++)
rfact[i] = binpow(fact[i], MOD - 2);
}
int choose(int x, int y)
{
if(x < 0 || y < 0 || x < y) return 0;
return mul(fact[x], mul(rfact[y], rfact[x - y]));
}
vector<int> prefix_sum(const vector<int>& a)
{
int n = a.size();
vector<int> p(n + 1);
for(int i = 0; i < n; i++) p[i + 1] = add(a[i], p[i]);
return p;
}
int get(const vector<int>& a, int i)
{
if(a.size() > i) return a[i];
else return a.back();
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int n, m, k;
cin >> n >> m >> k;
precalc_factorials();
vector<vector<int>> A(k, vector<int>(n + m));
for(int x = 0; x < k; x++)
{
vector<int> by_rows(n + 1);
for(int i = 1; i <= n; i++)
by_rows[i] = mul(choose(n, i), binpow(x, n - i));
vector<int> pr = prefix_sum(by_rows);
vector<int> by_cols(m + 1);
for(int i = 1; i <= m; i++)
by_cols[i] = mul(choose(m, i), binpow(x, m - i));
vector<int> pc = prefix_sum(by_cols);
for(int i = 1; i <= max(n, m); i++)
{
A[x][n + m - i] = sub(mul(get(pr, i + 1), get(pc, i + 1)), mul(get(pr, i), get(pc, i)));
}
}
for(int i = min(n, m); i < n + m; i++)
{
int ans = 0;
for(int j = 0; j < k; j++)
{
int cur = mul(choose(k - 1, j), A[k - 1 - j][i]);
if(j % 2 == 0)
ans = add(ans, cur);
else
ans = add(ans, -cur);
}
cout << ans << " ";
}
cout << endl;
}









G is pretty amazing and educational.
where can i find problems similar to D which don't scream DP but are/
This problem reminded me of a problem from here https://cses.fi/problemset/task/2229
IMO, this is the thing which is a bad habit in me. DP is a technique We don't need to think that wether a problem is DP or not in Disguise, its bad for Problem Solving. Problem Solving/CP is Seeing a Problem for what it is, drawing meaningful observations and then you observe some property and be like -> "Ohh!! I can handle this using Dynamic Programming" thats better. That will help you in solving Problem.
in D once we observe that we can break a the permutation into number of contiguous sorted segments and suppose they are $$$a_1, a_2 ... a_m$$$ one equation is $$$\sum_{i = 1}^m a_i = n$$$ and another is if we count inversion value its when we choose two elements of different segments so $$$\sum_{i, j \in m} a_i a_j = k$$$ Now simplifying this it basically translates to $$$\sum_{i = 1}^m a_i^2 = n^2 - 2k$$$. so Now our problem simplifies to partitioning $$$n$$$ in such partitions such that they obey the above two equations. Now let $$$S = n^2 - 2k$$$ not every $$$n$$$ can be partitioned in above way. so how can we check wether for any arbitrary $$$n, S$$$ they can be partitioned. Now if there exists some partition then $$$\exists$$$ $$$k$$$ s.t. if $$$n, S$$$ can be valid then $$$n - k, S - k^2$$$ should also be valid. So a recurrence we get $$$valid[n][S] = valid[n][S] | valid[n - x][S - x^2]$$$ for all valid $$$x$$$ Now after partitioning its easy to construct a permutation which is good.
Missing editorial for F btw
I was looking forward to editorial of F,please post it.
Fast Editorial! Nice!
D is a beautiful problem, but can we do better than $$$O(N^4)$$$. Overall B > C. I think E is solvable by SegBeats thought its overkill and I am getting TLE. Binary search with Segtree also Works
F is made easier by the fact that the greedy is correct (since $$$x$$$ and $$$x + 1$$$ can't both be trapped at the same time, it is optimal to advance whenever possible).
However, we can solve a more general version of the problem where there is no greedy, for example when instead of losing if $$$x$$$ mod $$$a_t = b_t$$$ at time $$$t$$$, we lose if $$$x$$$ mod $$$a_t \in B_t$$$ with $$$B_t$$$ a subset of $$$[0, 1, ..., a_t - 1]$$$.
For $$$m \lt = LCM$$$, we can simply run a classic $$$dp[LCM][n]$$$ to find the minimum distance from $$$(0, 0)$$$ to any state. For bigger $$$m$$$ however, we need to go through the torus multiple times (since the dp is cyclic in both variables, the graph looks like a torus).
For that, we can run the dp once to find the min distance from $$$(0, 0)$$$ to $$$(LCM, t)$$$ for each $$$t$$$, then run the dp again this time starting from $$$(0, 1)$$$, $$$(0, 2)$$$, and so on, until we have all minimum distances between $$$(0, i)$$$ and $$$(LCM, j)$$$ for $$$0 \leqslant i, j, \lt n$$$.
Once we have this $$$n * n$$$ matrix, it allows us to connect the start of the torus to its end, and all we need to do is to exponentiate it to the power $$$m / LCM$$$, and run the dp one final time to go through the last $$$m$$$ mod $$$LCM$$$ steps.
Time complexity : $$$O(n^2LCM + n^3log(m))$$$
Can anyone explain why order doesn't matter in problem B?
Because k<=n that means a same card can't be removed from both top & bottom, even if you do operation in any order. And all operation '2' will lie in middle of removed cards.
for eg., 2210 for any n>k After first 2 operation you are unsure about top 2 & bottom 2 cards but after 3rd operation you are sure at least 1 card is removed from bottom & after 4th you are sure at least 1 card is removed from top.
It is same for 1022 or 1220 Here also you are sure about 1 top & 1 bottom card.
And n==k is edge case where all cards are removed because you are removing n cards in total so type of operation & order of operation doesn't matters.
Got it. Thanks
D can be brute forced for n<80 in python (probably much higher in C++).
If you have answer for all k for a given n, you can find a valid answer for all k which have a valid solution for n+1 by just brute forcing n+1 at every possible position in answer for every k for n then compute the k for that permutation. Given how low the constraints are this will work just fine.
Try CF Submitter : https://marketplace.visualstudio.com/items?itemName=DevXSayan.cf-submitter - Fetch all the problems of a contest inside vscode, run test cases, and submit in one click, all without leaving vscode
I don't understand D T_T. How do people come up with this shi
stupid 4 pointer idea for B 342285913
Why is $$$n + m - \min(x, y)$$$ the number of operations for problem G?
Isn't it best to select the smallest one if there are $$$x$$$ rows and $$$y$$$ cols with color 1? The number of operations required, in my opinion, is $$$n + m - x - y + \min(x, y) = n + m - \max(x, y)$$$.
This is an error, thank you. I will fix it in a couple of minutes
Can please anyone explain why this one passes the sample case but fails on test 2, is it my approach is wrong or I missed the edge cases? for C:
I think problem B can be solved by Brute-Force and Deque data structure. Because the bottom card removal operation can cost O(n)(remove arr[0] in array ) and repeating it many times like that can make the complexity O(n^2) and it will be TLE. We can solve this problem by Deque which makes the bottom card removal only have complexity O(n) and helps the complexity of the code from O(n^2) to O(n)
This is just a suggestion on the solution of problem B improved from Brute-Force, please do not downvote me
have you solved problem b using this approach ?
That is my AC Code using deque (python): Code
There should be modification in solution of D!
We have to fill up dp & p earlier not in the loop as it will give TLE. I tried solution of editorial its giving TLE. But, if you calculate it earlier then it will work.
"There are other ways to solve this problem, for example, with functional graph cycle detection or fast matrix exponentiation, but in my opinion, this approach is the easiest to implement."
What would the functional graph cycle detection solution be like?
I had similar key idea for D, but with little bit different implementation. Our final permutation (if it exists) consists of several sorted segments with various length. Each of them contribute final answer by minus n*(n-1)/2, so we need to find segments whose sum equal to n*(n-1)/2 — k. Thus we can use knapsack dp to brute force all possible length and find their numbers and length. It will look like dp[i][1][2][3]...[30] right from 1 to n, i represent sum and left 30 numbers are counters of segments with length of its corresponding index. The transition is simple, just like in an ordinary knapsack, taking value from dp[i-op] and changing all its numbers with adding +1 to chosen length. Oh and dp itself is the sum of the length of the taken. So in the last step we just check whether dp[n*(n-1)/2 — k][0] is less or equal than n, and building permutation just like in editorial. Link Here is submission for more details.
It is sad that there is no interactive problem :(
It is sad that there is no interactive problem in this contest :(
Could someone clarify what the editorial author meant when they said "Iterate over K — the length of the next sorted block"?
Can someone please tell what was wrong with my solution in "problem C" as I use d the same concept , stored all the consecutive a's and b's in map and as we know we can only remove once hence I found the difference between their counts and tried to find if it is present in the map.
Just realize, the DP in G is just ordered $$$k-1$$$ partitions of a set with $$$ n-x+m-y $$$ elements.
set partitions could be calculated recursive in $$$O(n^2)$$$: $$$ part(n, k) = part(n-1, k-1)+k*part(n-1, k) $$$
Very educational~
Can someone guide me on how to approach generation based problems? For example, Question D in this contest, where you are asked to generate an array that satisfies certain conditions. How should I approach these types of problems? If it’s too much to explain in a comment, a link to a post or tutorial would be appreciated.
Salam
Why greedy doesn't work on D?
Hello, I received a message that my submission (342267062) coincides with submission 342268142 from another account. Both accounts (Mim5270 and akthermim) actually belong to me. I understand now that having multiple accounts and submitting the same solution was a mistake — I did not intend to break any rules or gain an unfair advantage. I sincerely apologize for the violation and assure you it won’t happen again. Please consider this my explanation. I will only use one account from now on. Thank you for your understanding.
My 342314871 for D without any DP (there is dp in my code but its just (i * (i — 1)) / 2)
I'm using brute force and check all possible set of length's for increasing subsegments.
Here is a soltion to solve problem 2145D - Inversion Value of a Permutation without using DP.
First,transform the problem meaning in the same way as the solution. We need to select some items which has $$$i$$$ value and $$$i+1 \choose 2$$$ weight and make the sum of value equal n and the sum of weight equal k.
Second,to do this,we have noticed the partition of $$$30$$$ is less than $$$6000$$$! So we can just use the brute force to solve this problem.
342894423
i found a pretty ez dp solution which is kind of take it or leave it approach that helps find the position of the inversions , and you can just construct the permutation using these inversions with a little bit of dfs ahh approach https://codeforces.me/contest/2145/submission/343178829
its another nice solution all in all that requires no math or any extras , keeping it simple enough
let me know what you think
Can someone tell me what is wrong with this code 349836610 for problem D
i got WA on this testcase:
1 5 10
but when i ran it has the right output
2145C is a very good ques , it seems like easy on first go. but it quite different to think on first hand while u are writing code their are two -1 testcases wont work , it took around 2 hours for the whole code but took 5-6 hours of effort to deal with that -1 testcase :(. but it was worth the time
In F,the "at the end of moves",is it mean "at the end of turns"?
Nice and elegant solution for D. But I'm lacking intuition why is it possible to construct any number using sum of $$$\frac{i_1*(i_1-1)}{2}+\frac{i_2*(i_2-1)}{2}+...$$$ and if it's not possible, then why are we certain that it's not possible to construct the answer in other way than in the editorial?
B is dog shit