We hope that you have enjoyed our problems!
Idea by Mindeveloped, prepared by Mindeveloped
It is always possible to rearrange the candies, unless candies of one specific color appears too often.
Let $$$x$$$ be the color with the highest number of candies. In case of ties, $$$x$$$ could be any of the candidates. Denote the number of candies with color $$$x$$$ as $$$a$$$.
Conclusion: The answer to the problem is YES if and only if there are no more than $$$n^2 - n$$$ candies of color $$$x$$$; — in other words, $$$a\le n^2 - n$$$ holds.
Proof of necessity: If there are more than $$$n^2 - n$$$ candies of color $$$x$$$, then there are less than $$$n$$$ candies not of color $$$x$$$. Since there are $$$n$$$ rows, at least one row will have no candies not of color $$$x$$$; therefore, such a row will be filled with candies of color $$$x$$$, violating the restrictions.
Proof of sufficiency: If there are no more than $$$n^2 - n$$$ candies of color $$$x$$$, we can always construct a solution with the method below.
First, if $$$a \lt n$$$ holds, then we can arrange the candies arbitrarily because no color has enough candies to fill a row or a column.
Otherwise, $$$n\le a\le n^2 - n$$$ holds.
We can put candies of color $$$x$$$ in $$$a_{1,1},a_{2,2},\ldots,a_{n,n}$$$. This will take $$$n$$$ candies of color $$$x$$$. Next, we choose $$$n$$$ candies not of color $$$x$$$ arbitrarily. We will put them at $$$a_{1,2},a_{2,3},\ldots,a_{n-1,n},a_{n,1}$$$. Lastly, we arrange other candies that have not yet been arranged arbitrarily. Since in the first step we put a candy of color $$$x$$$ in each row and column, and in the second step we put a candy not of color $$$x$$$ in each row and column, each row and column contains at least candies of two colors, satisfying the constraints.
#include<bits/stdc++.h>
#define F(i,x,y) for (int i=(x);i<=(y);i++)
#define R(i,x,y) for (int i=(x);i>=(y);i--)
#define p2i pair<int,int>
#define ll long long
#define fi first
#define se second
#define nb(x) (1<<((x)-1))
#define x1 __melody1
#define x2 __melody2
#define y1 __melody3
#define y2 __melody4
#define iosoptim ios::sync_with_stdio(0);cin.tie(0);
using namespace std;
const bool MT = 1;
int n,cnt[10005];
void ygg(){
cin>>n;
int tmp;
bool flag=1;
F(i,1,n*n) {
cin>>tmp;
++cnt[tmp];
if (cnt[tmp]>n*(n-1)) flag=0;
}
if (flag) cout<<"YES\n";
else cout<<"NO\n";
}
void mark() {
F(i,1,n*n) cnt[i]=0;
}
int main (){
#ifdef ONLINE_JUDGE
iosoptim
#endif
int testcases=1;
if(MT) cin>>testcases;
while(testcases--){
ygg();
mark();
}
return 0;
}
Idea by Mindeveloped, prepared by Mindeveloped
For the sake of simplicity, let's assume all cards have different costs. If multiple cards have the same cost, we break ties by their initial position in the deck (the earlier card is considered to have a lower cost for the purpose of the strategy).
The optimal strategy: If the win-condition is among the first $$$k$$$ cards, then we play it. Otherwise, we play the card in the first $$$k$$$ places with the lowest cost. Proof of optimality is shown below.
Lemma: If at any time, the win-condition is placed at position $$$x \gt k$$$, the cost used before the win-condition is played again is at least the sum of the costs of $$$x-k$$$ cards with the lowest costs out of all the $$$x-1$$$ cards placed before the win-condition. Our strategy reaches this minimum value.
Proof:
Since playing any card in front of the win-condition moves the win-condition 1 place toward the front, we need to play $$$x-k$$$ normal cards before the win-condition is playable.
Before the win-condition moves to position $$$k$$$ and becomes playable, every card placed before the win-condition can be played at most once, and every card placed at the back of the win-condition cannot be played. Therefore, the cost used is at least the sum of the first $$$x-k$$$ lowest costs of the cards initially placed before the win-condition. We mark the $$$x-k$$$ cards placed before the win-condition with the lowest costs.
Among all the $$$x-1$$$ cards placed before the win-condition, exactly $$$k-1$$$ cards are not marked, so whenever before the win-condition is played the first time, at least one marked card will be in the first $$$k$$$ places. Therefore, our strategy will always play a marked card in the first $$$x-k$$$ plays since their costs are always lower than not marked ones. Since each marked card can be only played for at most once, after $$$x-k$$$ plays we will play each marked card once, which achieves the lower bound described above.
Therefore, the lemma is proven.
Now, let $$$A$$$ be the sum of the costs of $$$p-k$$$ cards with the lowest costs placed before the win-condition. Let $$$B$$$ be the sum of the costs of $$$n-k$$$ cards with the lowest costs, without considering the win-condition.
By the above lemma, the cost spent before playing the win-condition the first time is at least $$$A$$$. After it is played each time, it always gets placed at position $$$n$$$, so the cost spent before playing the win-condition another time is at least $$$B$$$. Our strategy achieves the minimum.
Therefore, the cost used to play the win-condition any non-negative number of times is minimized, which proves the optimality of the strategy.
The answer is $$$\lfloor \dfrac{m-A-a_p}{B+a_p}\rfloor + 1$$$ if $$$m-A-a_p\ge 0$$$. Otherwise, the answer is $$$0$$$.
The value of $$$A$$$ and $$$B$$$ can be calculated with a priority queue in $$$O(n\log n)$$$. Therefore, the overall time complexity is $$$O(n\log n)$$$.
Alternatively, you may simulate the strategy above directly; the time complexity will be $$$O(nm)$$$, which is also sufficient to pass.
#include<bits/stdc++.h>
#define F(i,x,y) for (int i=(x);i<=(y);i++)
#define R(i,x,y) for (int i=(x);i>=(y);i--)
#define p2i pair<int,int>
#define ll long long
#define fi first
#define se second
#define nb(x) (1<<((x)-1))
#define x1 __melody1
#define x2 __melody2
#define y1 __melody3
#define y2 __melody4
#define iosoptim ios::sync_with_stdio(0);cin.tie(0);
using namespace std;
const bool MT = 1;
int n,k,p,a[100005];
ll m;
void ygg(){
cin>>n>>k>>p>>m;
F(i,1,n) cin>>a[i];
multiset<int> opt;
F(i,1,k-1) opt.insert (a[i]);
F(i,k,p-1) {
opt.insert (a[i]);
m-=*opt.begin ();
opt.erase (opt.begin ());
}
m-=a[p];
if (m<0) {
cout<<0<<"\n";
return;
}
ll sum=a[p];
opt.clear ();
F(i,1,n) {
if (i!=p) opt.insert (a[i]);
}
F(i,1,n-k) {
sum+=*opt.begin ();
opt.erase (opt.begin ());
}
cout<<1+m/sum<<"\n";
}
void mark() {
}
int main (){
#ifdef ONLINE_JUDGE
iosoptim
#endif
int testcases=1;
if(MT) cin>>testcases;
while(testcases--){
ygg();
mark();
}
return 0;
}
Idea by tybbs, prepared by tybbs
Notice that the value of $$$S$$$ does not affect your decision. This meant for integer $$$i\in[1,n-1]$$$ the decision of tasks $$$[1,i]$$$ does not affect the decision of tasks $$$[i+1,n]$$$.
Let $$$f_i$$$ be the answer for considering tasks $$$[i,n]$$$ only and assuming that $$$S=1$$$. It holds that $$$f_i=\max(f_{i+1},f_{i+1}\cdot(1-\frac{p_i}{100})+c_i)$$$, and $$$f_1$$$ is the answer needed.
#include<bits/stdc++.h>
#define ld long double
using namespace std;
const int N=1e5+5;
ld c[N],p[N];
void solve(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
int cv,pv;
cin>>cv>>pv;
c[i]=cv,p[i]=pv/100.0;
}
ld ans=0;
for(int i=n;i>=1;i--){
ans=max(ans,ans*(1-p[i])+c[i]);
}
cout<<fixed<<setprecision(10)<<ans<<"\n";
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int T;
cin>>T;
for(int i=1;i<=T;i++) solve();
}
2208D2 - Tree Orientation (Hard Version)
Idea by tybbs, prepared by tybbs
If a solution exists, it must be unique.
Assume a solution exists, construct the graph accordingly, and verify afterward that it satisfies all given conditions.
Consider the necessary and sufficient condition for the existence of a directed edge $$$ u \to v $$$.
Two conditions must hold:
1. Node $$$ v $$$ must be reachable from $$$ u $$$.
2. There must be no intermediate node $$$ w $$$ such that $$$ u $$$ can reach $$$ w $$$ and $$$ w $$$ can reach $$$ v $$$.
Implementing this directly yields an $$$ O(n^3) $$$ solution, which is sufficient for D1. One can further optimize it to $$$ O\left(\frac{n^3}{\omega}\right) $$$ using bitsets, though this is not required for this subtask.
Let $$$ R_u $$$ denote the set of nodes reachable from $$$ u $$$, excluding $$$ u $$$ itself.
Let $$$ s_u $$$ denote the number of nodes reachable from $$$ u $$$. Among all nodes in $$$ R_u $$$, let $$$ v $$$ be the one with the largest $$$ s_v $$$. What can we infer?
It can be proven that the edge $$$ u \to v $$$ must exist in the solution.
We iteratively apply the idea from Hint 4:
- Find the node $$$ v \in R_u $$$ with the largest $$$ s_v $$$, and add the edge $$$ u \to v $$$.
- Then remove all nodes in $$$ R_v $$$ from $$$ R_u $$$, since they are already reachable from $$$ u $$$ indirectly via $$$ v $$$, and therefore cannot have a direct edge from $$$ u $$$.
- Repeat this process until $$$ R_u $$$ becomes empty. At that point, all outgoing edges from $$$ u $$$ have been determined.
Since the final graph is a tree with exactly $$$ n - 1 $$$ edges, the total number of such removal operations across all nodes is $$$ O(n) $$$. Each operation involves scanning or updating a set of size at most $$$ n $$$, leading to an overall time complexity of $$$ O(n^2) $$$.
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 1e4+5;
int n, id[N], cnt[N];
bool vs[N], e[N][N];
struct Dsu {
int fa[N];
void init(int n) {
for (int i = 1; i <= n; i++) fa[i] = i;
}
int find(int x) {
if (x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
void merge(int x, int y) {
fa[find(x)] = find(y);
}
} dsu;
bool reach[N];
vector<int> tree[N];
void search(int u) {
reach[u] = 1;
for (int v : tree[u]) {
search(v);
}
}
void solve(int tid) {
cin >> n;
for (int i = 1; i <= n; i++) cnt[i] = 0, tree[i].clear();
for (int u = 1; u <= n; u++) {
id[u] = u;
string s;
cin >> s;
for (int v = 1; v <= n; v++) {
e[u][v] = s[v-1]-'0';
cnt[u] += e[u][v];
}
}
sort(id + 1, id + n + 1, [&](int u, int v) {
return cnt[u] > cnt[v];
});
vector<pair<int, int >> edges;
for (int u = 1; u <= n; u++) {
for(int i = 1; i <= n; i++) {
vs[i] = false;
}
vs[u] = true;
for (int i = 1; i <= n; i++) {
int v = id[i];
if (!vs[v] && e[u][v]) {
edges.push_back({u, v});
if(edges.size() >= n) {
cout << "No" << "\n";
return ;
}
for (int w = 1; w <= n; w++) {
if (e[v][w]) {
vs[w] = true;
}
}
}
}
}
if (edges.size() != n - 1) {
cout << "No" << "\n";
return ;
}
sort(edges.begin(), edges.end());
dsu.init(n);
for (auto [u, v] : edges) {
dsu.merge(u, v);
tree[u].push_back(v);
}
int flag = 1;
for (int i = 1; i <= n; i++) flag &= (dsu.find(i) == dsu.find(1));
if (!flag) {
cout << "No" << "\n";
return ;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) reach[j] = 0;
search(i);
for (int j = 1; j <= n; j++) {
if (reach[j] != e[i][j]) {
cout << "No" << "\n";
return ;
}
}
}
cout<< "Yes\n";
for (auto [u, v] : edges) {
cout << u << ' ' << v << '\n';
}
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
int T;
cin >> T;
for (int i = 1; i <= T; i++) solve(i);
return 0;
}
Idea by tybbs and Mini_PEKKA, prepared by tybbs
Find a straightforward criterion to determine whether an array is "cute".
First, consider a necessary condition: If $$$X_i \ge i$$$ for any $$$i$$$, the array $$$X$$$ cannot be cute.
It is well-known that the structure of $$$X$$$ relates to a monotonic stack. We can verify whether an array $$$X$$$ of length $$$n$$$ is cute using the following simulation procedure:
- Maintain a stack $$$S$$$, initialized with a single sentinel element $$$0$$$.
- Iterate $$$i$$$ from $$$1$$$ to $$$n$$$:
- Check if the value $$$X_i$$$ exists in $$$S$$$.
- If $$$X_i$$$ is not in $$$S$$$, then $$$X$$$ is not a cute array.
- If $$$X_i$$$ is in $$$S$$$, pop elements from $$$S$$$ until $$$X_i$$$ becomes the top element. Then, push $$$i$$$ onto the stack.
- If the loop completes without violating the conditions above, $$$X$$$ is a cute array.
Solve the problem for the following special case: For all $$$i$$$, $$$X_i$$$ is either $$$-1$$$ or $$$i-1$$$.
We can use dynamic programming to solve this special case. Let $$$f_{i,k}$$$ denote the number of ways to fill the $$$-1$$$s in the prefix $$$X_1 \dots X_i$$$ such that the array remains potentially cute and the current stack size is $$$k$$$.
The transition is straightforward: * If $$$X_i = -1$$$, we can pop an arbitrary number of elements. Thus, $$$f_{i,k} = \sum_{j=k-1}^{i} f_{i-1,j}$$$. * If $$$X_i = i-1$$$, we cannot pop any elements (the previous index must be the nearest greater element). Thus, $$$f_{i,k} = f_{i-1,k-1}$$$.
Analyze the failure condition of the stack procedure further.
If $$$X_i$$$ is not found in $$$S$$$ during the simulation, it implies that $$$X_i$$$ was previously popped from the stack while processing some earlier index $$$j$$$. This indicates the existence of a pair $$$(j, i)$$$ such that $$$X_j \lt X_i \lt j \lt i$$$.
Consequently, an array $$$X$$$ is cute if and only if no such pair $$$(j, i)$$$ exists that satisfies this condition.
First, check if all fixed values (where $$$X_i, X_j \neq -1$$$) satisfy the condition that no pair $$$(j, i)$$$ with $$$j \lt i$$$ exists such that $$$X_j \lt X_i \lt j \lt i$$$. Additionally, ensure $$$X_i \lt i$$$ for all $$$i$$$. If these conditions are not met, the answer is $$$0$$$.
Consider each fixed $$$X_i \neq -1$$$ as defining an interval $$$[X_i, i]$$$. By sorting these intervals by length from smallest to largest, we can process them hierarchically. Once all $$$X_k$$$ within a specific interval are determined, the interval effectively behaves like the base case $$$[i-1, i]$$$ mentioned in Hint 2.
This reduction transforms the general problem into the special case solved in Hint 2. We can compute the final answer using the DP approach with prefix sum optimization, resulting in an overall time complexity of $$$O(n^2)$$$.
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5,mod=998244353;
inline void add(int &x,int v){ x=(x+v)%mod; }
int T,n,ans,a[N],id[N],mx[N],f[N],sf[N];
void calc(int l,int r){
int tp=0,cnt=0;
f[0]=1,sf[0]=1;
while(1){
if(mx[l]==0) l++,tp=0;
else l=mx[l],tp=1;
if(l>r) break;
cnt++;
if(tp==0){
for(int i=1;i<=cnt;i++) f[i]=sf[i-1];
f[0]=0;
}
else{
for(int i=cnt;i>=1;i--) f[i]=f[i-1];
f[0]=0;
}
sf[cnt+1]=0;
for(int i=cnt;i>=0;i--) sf[i]=(sf[i+1]+f[i])%mod;
}
ans=1ll*ans*sf[0]%mod;
}
void solve(){
cin>>n;
for(int i=0;i<=n;i++) mx[i]=0;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
if(a[i]>=i) return void(cout<<0<<"\n");
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(a[i]!=-1 && a[j]!=-1){
if(a[i]<a[j] && a[j]<i) return void(cout<<0<<"\n");
}
}
}
int cnt=0;
for(int i=1;i<=n;i++){
if(a[i]!=-1) id[++cnt]=i;
}
sort(id+1,id+cnt+1,[](int x,int y){ return x-a[x]<y-a[y]; });
ans=1;
for(int i=1;i<=cnt;i++){
calc(a[id[i]],id[i]-1);
mx[a[id[i]]]=id[i];
}
calc(0,n);
cout<<ans<<"\n";
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>T;
for(int i=1;i<=T;i++) solve();
}








Auto comment: topic has been updated by Mindeveloped (previous revision, new revision, compare).
Auto comment: topic has been updated by Mindeveloped (previous revision, new revision, compare).
When you solve problem B:
fr, had a hard time implementing it!!
On the Generalization of the Problem
What if the input comes from any directed graph rather than a directed tree?
Just check the construction afterward
I slept solving e lmao mid contest also b can also be solved with rmq seg tree
I think the formula for f[i] is wrong in the editorial for problem C. Shouldn't it be
f[i] = max(f[i + 1] , f[i + 1] * (1 — p[i] / 100) + c[i]).
fixed
I was able to simulate problem B in around N*log(N) time complexity by putting the first k elements in a priority queue and the rest of the elements in a queue.
Constraints chote the warna I guess I could've figured out aswell
I thought of the same thing ... But constraints were lower so simply used v.erase() each time
can anyone explain to me problem B in an easy way to understand?
It's like clash royale game, u have n cards and initially you have your win condition at index p and u have a segment of k from which any cards can be played (means you can play any card in the segment if the cards come in that segment) and you have energy of m if you play any card then a[i] energy will be used, so your task is to figure out how many times you can play win condition in that given energy
The solution is simple there are 2 cases first is the playing the win condition first time if the p is in k range then we can play win condition as first card and that card moves to the back of the queue and if the win condition is not in k range then we need to play (p-k) cards so we can play the win condition for first time , and then the second case after playing win condition for first time is that after every (n-k) cards you can play win condition again so you need a priority queue to play (n-k) cheap cards to maximize the play of win condition.
Correct me if my approach is wrong:)
It is the kind of problem that you need to deal with when you are playing a sneaky golem deck.
Hey I initially submitted my solution for problem A and it showed pretests passed but later when i viewed it , it showed verdict skipped so then i had to resubmit it (after 20 mins) which resulted in me losing points for this question.
Submission ID:https://mirror.codeforces.com/contest/2208/submission/366640037
What Should I do?
wow
My thought process during B was:
First, obviously you just gotta treat the array as a queue (except you can choose between the first k elements to pop) and then it's trivial!
Then, I forgot how to treat an array as a queue (using .append() and .pop()/.remove() in python)
Then, I came up with an O(k*n) solution which had one slight problem, if anyone's interested it'll be at the end of the comment
In implementing that overcomplicated solution I learned about .append() and .pop()/.remove()
And in the final 11 minutes I finally realized I could use those commands to trivialize the entire problem :(
The overcomplicated solution: - find k-1 biggest numbers in the deck (other than the target ofc) and remove them from the deck - then, find the cost to get the very first aquisition of the wincon. (sum of all elems between 0 and p not including p) - then, find the cost for each subsequent aquisition of the wincon (sum of entire array) - profit the logic being: in the actual solution you'd choose to take the cheapest card available at all times, meaning, after buying n cards you'd be left with k-1 cards that are the priciest being in your deck, plus one card slot that you repetitively use (ask for clarification if you want) and it doesn't work because
if the k-1 maximums are all after the wincon in the deck order, and you only have enough mana to cast the wincon once in total, you would remove the biggest numbers that are not obstructing the aquisition of the first wincon and then you wouldn't be able to get the first wincon and return 0 instead of (ask for clarification if needed)
sorry for rambling
it was a fun contest :)
i'm sorry why are you trying to take the biggest number if it's not obstructing the acquisition of the first winning card (i.e., it's after p), especially if you know the you have enough energy/mana to at least get the first winning card?
per your description of the "overcomplicated solution", this is following the right logic (imo). but i would include the cost of acquiring the winning card (i.e., include cost @ p) and the cost for each subsequent acquisition would be all the remaining cards (including p).
you can refer to my submission: 366703802 (ignore all the comments)
That was the problem with my logic, I needed to calculate the cost to get the first wincon separately and only then calculate the cost for each subsequent aquisition of the wincon.
Great problem E, loved it.
Problem C was interesting to me (since I think problem B is just pure implementation, and I'm not good at it).
My first thought was that we could use DP with a two-dimensional array: dp[i][S * 100] (just scale S by 100 since it's a percentage). But then I realized that it would exceed the memory limit.
So there must be a way to reduce the S dimension. That means it needs to become a constant at some point (sorry for this explanation, it's just how by brain work through this).
Then I realized that the only S that can always be determined is actually the first moment (where the problem states that the initial S = 1).
I came up with the same solution the author stated above.
can you expain what does this mean? the only S that can always be determined is actually the first moment
If you do the dp iteratively you can reduce the space by n since the state i depends only on (i + 1).
Actually, I have done with recursive dp space complexity of O(n) only
Can you share your code?
Yeah sure, here: DP REC CODE
Good Job!
The solutions and the problems themselves are kind of unclear.
In fact, a $$$O(n^3/w)$$$ solution passed the problem D2 using optimized bitsets by avx2 instructions when I'm testing.
I discussed this with problem setters, and we all agreed that nobody will pass the D2 by this method, so we didn't make changes to prevent optimized bitsets from being accepted.
accepted link
I guess, I got lucky to get it accepted using bitset (not the optimized bitset).
Accepted Link
u have suspicious comments in code
You have suspicious rating graph. With so less problems, you gained such a high rating.
Btw, I write comments in my code if I have solved the problem with a nice idea. Or else, if there is a chance that I could make mistakes in implementation, I first try to clarify my thought process by writing comments and then I implement my idea.
I am confused. For problem D, since the statement says that the given matrix is obtained from a tree, then why no solution situations still exist.
B can be simply brute-force with greedily picking the smallest in the first k elements. I could not do it if n up to 10^5 :(
Problem E was amazing but i feel like the editorial could've been a bit more clear about the idea behind it... it took me a while to understand how the dp is actually calculated
Holy florr reference in problem B's code xD
I think my solution for D2 should get TLE because its time complexity is O(n^3), but it actually passed.Could someone take a look please
366702216
In problem C, how does value of S has no impact ?
It does have an impact it's just how you interpret it:
The editorial just states that the optimal subset that you choose from i+1 to n (having chosen some till i) does not depend on what your S was at index.
In other words you could have started with S being equal to 2 and the final answer just would have been multiplied by 2.
For D2:
Why does it work to draw edge between a node and another node in its subset with largest subset size?
this helps in this way
since the suppose both u and v belongs to s
now lets assume that v is reachable from u, since v is reachable from u all nodes reachable from v will be reachable from u , therefore the size of set of reachable nodes will be greater of u than v,
therefore when allocating edges between nodes in clearing order of the size will ensure that no two cycle is formed ,as orgiral graph was a tree
add hint for task B
can anyone tell me why does it gets TLE on problem D2 I am pretty sure its O(N*N)
367132158
is there video solution for these queestion? i want to learn to implement trees and graphs for d1 and d2
I think Problem D2 should include a note stating that the data input for this problem is quite large, so please use a faster input method. I used an unbound
cin, which caused me to keep getting Time Limit Exceeded errors, resulting in a very poor problem-solving experience!well done
i brute forced B and got AC. wow.
I received a plagiarism warning for this round. I want to clarify that both accounts involved belong to me. I used them during the contest, which I now understand is against Codeforces rules.
I sincerely apologize for this mistake. I will use only one account for future contests and will strictly follow all rules.
You can ban the other account, but let me keep this one.
I think D is a wonderful problem!
Even after struggling with the question B for more than couple of hours, I had to look at the solution....
:(