### decoder123's blog

By decoder123, history, 5 years ago, Hi!

Tomorrow at 14:00 MSK will be held Topcoder SRM 695.

Let's discuss problems after contest! srm, 695, Comments (36)
 » is chrome ok? no posts of SRM by him since long time :/I miss him :(
•  » » did you hack him too?
•  » » Maybe He Just Preparing To The University
 » 5 years ago, # | ← Rev. 2 →   Can someone please explain the solution to Div1 Level 3?
•  » » Solution to the 800: If S % K = 0, then write S/K on both sides of the coin and we are always done.If S % K is not 0, then first notice that we can only win if there is at least one head and one tail. WLOG the first flip is heads, and consider the position of the first tail.If there are A heads and K-A tails in the end, we must have AX + (N-A)Y = S for X on the heads side and Y on the tails side. Note that if gcd(A,N-A) does not divide S, we cannot win in this case. Otherwise, pick X so that for each A with gcd(A,N-A) dividng S, there exists integer Y with AX + (N-A)Y = S. (This can be done by the Chinese Remainder Theorem, as we need A | S-NX for each of these A)Write X on the head of the coin. Once the first tails appears, we need to decide what to write. If there are C coin flips left, pick the A closest to (C/2) such that gcd(A,N-A) divides S. Then write the Y with AX + (N-A)Y = S. The probability of this scenario is (C choose A) / 2^K.
•  » » » I have question about this solution.In Chinese Remainder Theorem, the dividers need to be co-prime to each other, which is not ensured in this problem. How could we ensure we can find such X?
•  » » » » 5 years ago, # ^ | ← Rev. 3 →   Ok, we need to find integer X so that lcm(all possible A) | S-NX. The greatest common divisor of this LCM and N must divide S since gcd(A,N-A) divides S, which means that you can find such an integer X by Bezout.
 » 5 years ago, # | ← Rev. 2 →   Reads a statement about bears/Limak Immediately realises it's an Errichto's Round.
 » 5 years ago, # | ← Rev. 2 →   Can someone please explain some deterministic solution to div1 500? I didn't manage to use the fact about degree<=3 somehow so I just coded local optimization desperately.Upd. I've just read in chat room, picking an edge decreases cost of at most 5 edges, so there is no need to try something except of 35 best edges in our brute force solution. Got it :(
•  » » Each edge you pick diminishes value of at most 4 of the other edges, so take only 35 biggest edges and do brute force.
•  » » » I had this idea also. It reminds me of a COCI problem that appeared at some point.
•  » » » http://hsin.hr/coci/contest3_tasks.pdfProblem DOMINO
 » That was my first time in a SRM! :D The experience was awesome. ^_^ I've a question though. Is there any editorial for today's contest?
•  » » Don't expect the editorial to come out soon. They haven't published the editorial to SRM 694 yet. :(But you can ask the problems here. :)
 » How to solve div1 300 ??
•  » » 5 years ago, # ^ | ← Rev. 4 →   I will split the answer string into maximal constant substrings and store them in some container. (eg. abbaab has 4 components a, bb, aa, b). Once you have the sizes of all these components, you can assign 'a' and 'b' greedily. Keep assigning 'a' to the largest component, 'b' to the smallest, then 'a' to the largest and so on. Now to get these components. Iterate from n to 1 (assume x[] is 1-indexed). Store the components you have already found in some container. If you are at position i, decrease the value required by the number already contributed by all the components you've found already. If this value goes below zero, answer is not possible. Otherwise if remaining value is r, create r components of size i.Let's take a small example. Consider the vector {4, 2, 1}. At position 3, you create a component of size 3. At position 2, you get the new value as (2-(3-2+1)), which is 0. So you move on. Then at position 1, you get the new value as (4-(3-1+1)), which is 1. So you add 1 component of size 1. You have 2 components now, one of size 3 and one of size 1. Assign 'a' to the largest and 'b' to the smallest, to get the answer "aaab".Hope this helped. :)
•  » » » Yeah, it helped, thanx a lot :) ...
•  » » » Thanks for describing your solution satyaki3794. Unfortunately I feel like I'm missing something. What do you do if you have something like this {0, 0, 2, 0}. From my understanding you create 2 components of size 3, but this doesn't seem right since then your final string will have length of 6 chars while one with 4 chars is needed.Furthermore, how exactly do you decrease the value of all the components found already. E.g., what exactly are the numbers in your calculations: (2-(3-2+1)) and (4-(3-1+1))?
•  » » » » Please refer to my code.Also, I have added a check for ans.length() == n at the end, to take care of the problem you mentioned.As regards to the value (2-(3-2+1)) at pos 2 (1-indexed array), 2 is the required number of constant substrings of length 2 and (3-2+1) is the number contributed by some constant substring already found (in my above example, there is only one of length 3).
•  » » My solution was: the final string will be made of various segments of 'a's and 'b's. Let ai be the number of these segments of length i. Then ai satisfy a system of linear equations that involve xi. They also all need to be non negative and the sum of i * ai needs to sum to N.I solve that system, verify the solution and generate the output string.
 » 5 years ago, # | ← Rev. 2 →   My codes in Java. There are two approaches for div1-med. Mine was "choose some K of the initially-best 5*(K-1)+1 edges, in complexity C(5·(K - 1) + 1, K)". The other one was resursive "find the best edge and either take it or take some two neighbours". div2-easy public double totalDistance(int[] a, String dir) { double ans = 0; int x = 0, y = 0; for(int i = 0; i < a.length; ++i) { ans += a[i]; switch(dir.charAt(i)) { case 'N': y += a[i]; break; case 'S': y -= a[i]; break; case 'W': x -= a[i]; break; default: x += a[i]; } } return ans + Math.sqrt(x * x + y * y); }  div2-med public String findPassword(int[] x) { int n = x.length; if(x != n) return ""; ArrayList list = new ArrayList(); for(int i = n - 1; i >= 0; --i) { int val = x[i]; if(val < 0) return ""; if(val > 0) { for(int rep = 0; rep < val; ++rep) list.add(i + 1); for(int j = i - 1; j >= 0; --j) x[j] -= val * (i - j + 1); } } Collections.sort(list); String ans = ""; for(int i = 0; i < list.size(); ++i) { for(int rep = 0; rep < list.get(i); ++rep) ans += "a"; ++i; if(i < list.size()) for(int rep = 0; rep < list.get(i); ++rep) ans += "b"; } return ans; }  div2-hard final int MOD = 1000 * 1000 * 1000 + 7; int mul(int a, int b) { return (int) ((long) a * b % MOD); } ArrayList[] w; int[] dist; boolean[] forbidden; // for fixed (a, b) which vertices are too far from a or b boolean[] must; // for fixed (a, b) vertices on a path a-b must be taken void dfs_dist(int a, int par) { for(int b : w[a]) if(b != par) { dist[b] = dist[a] + 1; dfs_dist(b, a); } } int dfs_count(int a, int par) { int m = 1; for(int b : w[a]) if(b != par && !forbidden[b]) { m = mul(m, dfs_count(b, a)); if(must[b]) must[a] = true; } if(!must[a]) ++m; // maybe we don't take this vertex at all return m % MOD; } int forFixedPair(int a, int b, int n) { forbidden = new boolean[n]; for(int rep = 0; rep < 2; ++rep) { dist = new int[n]; dfs_dist(a, -1); for(int i = 0; i < n; ++i) if(i != b && dist[i] >= dist[b]) forbidden[i] = true; // swap(a, b) int tmp = a; a = b; b = tmp; } must = new boolean[n]; must[b] = true; return dfs_count(a, -1); } public int countSubtrees(int[] a, int[] b) { int n = a.length + 1; w = new ArrayList[n]; for(int i = 0; i < n; ++i) w[i] = new ArrayList(); for(int i = 0; i < n - 1; ++i) { w[a[i]].add(b[i]); w[b[i]].add(a[i]); } int ans = 0; for(int i = 0; i < n; ++i) for(int j = i; j < n; ++j) ans = (ans + forFixedPair(i, j, n)) % MOD; return ans; }  div1-easy public String findPassword(int[] x) { int n = x.length; if(x != n) return ""; ArrayList list = new ArrayList(); for(int i = n - 1; i >= 0; --i) { int val = x[i]; if(val < 0) return ""; if(val > 0) { for(int rep = 0; rep < val; ++rep) list.add(i + 1); for(int j = i - 1; j >= 0; --j) x[j] -= val * (i - j + 1); } } Collections.sort(list); String ans = ""; int i = 0; int j = list.size() - 1; while(i <= j) { for(int rep = 0; rep < list.get(j); ++rep) ans += "a"; --j; if(i <= j) for(int rep = 0; rep < list.get(i); ++rep) ans += "b"; ++i; } return ans; }  div1-med int[] citizens; int bestAns = 0; void rec(int i, int upTo, int remaining, Edge[] edges, int ans) { if(remaining == 0) { bestAns = max(ans, bestAns); return; } if(i == upTo) return; // 1) don't take this edge rec(i + 1, upTo, remaining, edges, ans); // 2) take this edge if(remaining > 0) { int a = edges[i].a; int b = edges[i].b; int memoA = citizens[a]; int memoB = citizens[b]; ans += memoA + memoB; citizens[a] = citizens[b] = 0; rec(i + 1, upTo, remaining - 1, edges, ans); citizens[a] = memoA; citizens[b] = memoB; } } public int maxHappy(int[] x, int[] a, int[] b, int K) { citizens = x; int n = x.length; int m = a.length; Edge[] edges = new Edge[m]; for(int i = 0; i < m; ++i) edges[i] = new Edge(a[i], b[i], x[a[i]] + x[b[i]]); Arrays.sort(edges); rec(0, min(m, 5 * (K - 1) + 1), K, edges, 0); return bestAns; }  div1-hard public long winProbability(int k, int s) { long[][] C = new long[k][k]; for(int i = 0; i < k; ++i) { C[i] = 1; for(int j = 1; j <= i; ++j) C[i][j] = C[i-1][j-1] + C[i-1][j]; } s = (s % k + k) % k; if(s == 0) return 1L << k; boolean[] ok = new boolean[k]; for(int i = 0; i < k; ++i) { int val = s + i * k; for(int j = 1; j < k; ++j) if(val % j == 0) ok[j] = true; } long ans = 0; for(int so_far = 1; so_far < k; ++so_far) { int remaining = k - so_far - 1; // a, a, ..., a, b, suffix_of_size_remaining long best = 0; for(int cnt_b = 1; cnt_b <= remaining+1; ++cnt_b) if(ok[cnt_b]) best = max(best, C[remaining][cnt_b-1]); ans += best; } // multiply by 2 because we don't care about the result of the first toss return ans * 2; } 
•  » » could you please elaborate a bit on div2-hard?
•  » » » Every valid subtree has a unique diameter. The main idea is to iterate over O(n2) possible diameters. For a fixed pair of vertices (a, b) we are interested in the number of subtrees with the following properties: Vertices a and b belong to a subtree. It means that everything on a path between them also must belong to a subtree. There should be no vertices v that dist(v, a) ≥ dist(a, b) or dist(v, b) ≥ dist(a, b) because then (a, b) wouldn't be a unique diameter. You should mark some vertices v as forbidden and on the remaining vertices run an O(n) dynamic programming solution. Check my code for details.
•  » » 4 years ago, # ^ | ← Rev. 2 →   Could you explain Div2-Med a bit please? Esp. this part: ~~~~~ for(int j = i — 1; j >= 0; --j) x[j] -= val * (i — j + 1); ~~~~~ Why do we reduce the values and then check if x[j] going < 0 will return an invalid password. Am not able to get the intuition behind this. Seems like something to do with combinations.
•  » » » Let's say the input says that there are no intervals of length bigger than 5. But it says that there are two intervals of length 5. Each of those two intervals generate some smaller intervals. In an interval of length 5 there are: two intervals of length 4 three intervals of length 3 four intervals of length 4 five intervals of length 5 The solution is to subtract those and then move on — check if the input says something about some smaller intervals that weren't simply generated by bigger intervals (here: intervals of length 5).
•  » » » » 4 years ago, # ^ | ← Rev. 2 →   I understand now. Although you mean to say: two intervals of length 4 three intervals of length 3 four intervals of length 2 five intervals of length 1
•  » » Could please explain where number "5 * (K — 1) + 1" in your Div1-medium solution come from? I know picking 1 edge will affect cost of at most 5 other edges, but it doesn't seem obvious.
•  » » » Let's say that we already know k - 1 edges from some optimal solution. These edges affect at most 5(k - 1) edges in total. So, at the beginning you can sort edges by "the-sum-of-values-of-two-connected-vertices" and right now the best k-th edge to add is for sure one of 5(k - 1) + 1 best ones from the beginning. Because at least one of first 5(k - 1) + 1 edges isn't affected by already chosen k - 1 edges. And that "at least one" edge isn't worse that edges outside the set of first 5(k - 1) + 1 edges.Using the logic above, one can prove that there exists an optimal solution using edges only from the set of first 5(k - 1) + 1 edges.
•  » » can you explain solution for div 1 easy
 » can someone explain div2 medium?
•  » » 5 years ago, # ^ | ← Rev. 3 →   You can think about the problem in this way:Let S be the answer we returned, and it can always be split into a consecutive sequence of 'a', then 'b', alternatively, etc. Let L, L, ..., L[t] be the length of each consecutive sequence of same character.For x[i], if L[j] >= i, then it will contribute L[j]-i+1 to x[i]. So x[i + 1] can be computed from x[i] in the following way: x[i+1] = x[i]-(# of L[j] >= i + 1)-(# of L[j] == i), this is equivalent to x[i+1]-x[i] = # of L[j] >= iSince we know how many L[j] has length at least i, we can thus construct an answer.
 » div2 medium not able to get solution?
•  » » Here is my source: http://pastebin.com/N2TNgWD8The logic I follow is from biggests to smallests because biggests contains smallests. So lets say if x = {4, 2, 1, 0}. We check x it is zero so we have nothing to do. We check x = 1. Also we calculate how many 3-length substrs there are already. There are zero, so we need to construct one. The resulting string is res = "aaa" Next time we will start with the letter 'b'. x = 2, we have already two substrs of length 2, so we dont add anything. Finally x = 4, so because we have already three we just need to add one new, so resulting res = "aaab". I hope it helps.
•  » » » thanks now i understood
•  » » » Very nice explanation. Thanks.
 » May anyone tell the idea of the Div.2 500 problem?