Educational Codeforces Round 117 (Rated for Div. 2)
A. Distance
https://codeforces.com/contest/1612/problem/A
The conditions given in the title are
The distance is Manhattan distance, which is equivalent to step size.
From the half condition of the topic, we can get that the step size and are ab step size, and each step size is half of AB step size.
Therefore, it is obvious that:
//Original code #include<bits/stdc++.h> using namespace std; int t; int main() { scanf("%d",&t); while(t--) { int x,y; scanf("%d%d",&x,&y); if((x+y)%2!=0) printf("-1 -1\n"); else if(x%2==0&&y%2==0) printf("%d %d\n",x/2,y/2); else if(x%2!=0&&y%2!=0) { if(x>y) printf("%d %d\n",(x+y>>1)-y,y); else printf("%d %d\n",x,(x+y>>1)-x); } } return 0; } //update #include<bits/stdc++.h> using namespace std; int t; int main() { scanf("%d",&t); while(t--) { int x,y; scanf("%d%d",&x,&y); int p=x+y,q=x/2; if(p%2!=0) printf("-1 -1\n"); else printf("%d %d\n",q,p/2-q); } return 0; }
B. Special Permutation
https://codeforces.com/contest/1612/problem/B
For the sequence with the title of 1-n, construct a double sequence with the length of n/2 to ensure that a is the smallest in the left half and b is the largest in the right half
So obviously we can construct it like this
a is placed in the front, and then the left half is the largest. Similarly, the right side
#include<bits/stdc++.h> using namespace std; int cnt,t,n,a,b; int main() { scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&a,&b); int t=n/2; if(a==t+1&&b==t-1) {for(int i=a;i<=n;i++) printf("%d ",i);for(int i=b;i>=2;i--) printf("%d ",i);printf("1\n");} else if(a>t||b<t) puts("-1"); else {for(int i=n,cnt=0;cnt==t;i--) if(i!=b) printf("%d%c",i,(++cnt==t?'\n':' '));for(int i=1,cnt=0;cnt==t;i++) if(i!=a) printf("%d%c",i,(++cnt==t:'\ ':' '));} }
C. Chat Ban
https://codeforces.com/contest/1612/problem/C
The topic is a triangle structure, plus an arithmetic sequence, what is the number of the first column to exceed.
Just two points directly.
This is a very classic and obvious dichotomy. The dichotomy is very important in two parts, one is dichotomy, and the other is the check function.
If we get banned after yy messages, we also get banned after y+1y+1, y+2y+2 and so on messages (and vice versa, if we don't get banned after yy messages, we also don't get banned after y−1y−1, y−2y−2 and so on messages).
The structure of triangle is divided into two parts. One part is y < = k, which directly uses the summation formula of arithmetic sequence, and the other part is Y > k, which needs to use half plus arithmetic summation
Finally, the formula is obtained
Two points. Just find the first one > =
#include<bits/stdc++.h> using namespace std; typedef unsigned long long ll; ll k,x,all; int t; ll get(int x){return x*1ll*(x+1)/2;} bool check(ll mid) { if(mid<=k) return get(mid)>=x; else return (get(k)+get(k-1)-get(2*k-1-mid))>=x; } int main() { scanf("%d",&t); while(t--) { scanf("%llu%llu",&k,&x); ll l=0,r=2*k-1; while(l<r) { ll mid=l+r>>1; if(check(mid)) r=mid; else l=mid+1; } printf("%llu\n",r); } return 0; }
D. X-Magic Pair
https://codeforces.com/contest/1612/problem/D
A simple math problem
When you see the operation set =d, it is easy to find that this is a monotonic decreasing process. You must assign a distance to one of them, and there are no more than three relationships: greater than, less than, or equal to.
If it is assigned to a large one, the distance will become smaller. If it is assigned to a small one, the distance may become smaller or larger. If it is equal to 0, note that once it is 0, it will cycle directly. The distance is always equal to a value, and must be assigned to 1, then either 0, d, or d,d.
For the first two cases, if it is the first one, is it obviously like rolling division? But here it is more subtractive. Therefore, if x occurs in the process of subtracting the large from the small, it is true. Then it is equivalent to (b-x)% a==0
For the second case, if it is assigned to a small one, the second distance will become one of the previous a and B, so it must be assigned to one of them, and it will either change back to the original or become the case of case 1.
So to sum up: just simulate the process of rolling division, as long as it occurs in the monotonic decline process. At the same time, once it is 0, there will be a cycle. At this time, you can exit.
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll a,b,x; int T; int main() { scanf("%d",&T); while(T--) { scanf("%lld%lld%lld",&a,&b,&x); bool flag=false; if(a>b) swap(a,b); if(a==x||b==x) {puts("YES");continue;} while(a!=0&&b!=0) { if((b-x)%a==0&&(b-x)>=0){puts("YES");flag=true;break;} else { ll tmp=a; a=b%a,b=tmp; } } if(!flag) puts("NO"); } return 0; }
E. Messages
https://codeforces.com/contest/1612/problem/E
The title is about n students. Everyone reads k[i] letter, and then wants to read the m[i] letter. You can pin a pile of letters. Ask for expectation. This question gives me a new way to write probability questions.
t is very small, only 20, and it is the same for parts greater than 20.
Just enumerate.
Sort them from large to small, select the value of each one, and then select it from the bottom. Compare all the selections.
Time complexity O (n^2logn)
#include<bits/stdc++.h> #define x first #define y second using namespace std; const int N=2e5+52,K=20; typedef long long ll; typedef pair<int,int> PII; int m[N],k[N],n; bool frac_greater(pair<int, int> a, pair<int, int> b)//Comparison mode { return a.first * b.second > a.second * b.first; } int main() { scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d %d",&m[i],&k[i]);//Everyone's situation, the first few letters, read k letters vector<int> ans1;//Store everyone's information PII ans2={0,1};//Storage results for(int i=1;i<=K;i++)//Because the maximum is 20, the calculation of the excess 20 will be smaller, and the excess 20 is equal to 20 { vector<int> score(N);//Open N bits, each bit is 0 for(int j=0;j<n;j++) score[m[j]]+=min(i,k[j]);//Get the situation of each letter. If this letter is selected (if it is selected, and the small is 1, otherwise it is k[j], and if it is not selected, it is 0) vector<PII > val;//Bucket sorting for(int j=0;j<N;j++) val.push_back({score[j],j}); sort(val.rbegin(),val.rend()); PII cur_ans={0,i}; vector<int> lt; for(int j=0;j<i;j++)cur_ans.x+=val[j].x,lt.push_back(val[j].y); if(frac_greater(cur_ans,ans2)) ans2=cur_ans,ans1=lt; } printf("%d\n",ans1.size()); for(auto x:ans1) cout<<x<<" "; puts(""); return 0; }
F. Armor and Weapons
https://codeforces.com/contest/1612/problem/F
Question F is a greedy question. There are probably two things, and then reach the target point through some conditions.
First reaction: greedy, shortest path (I don't know why many problems can be directly linked to graph theory, or indirectly linked to graph theory. I've seen a lot in recent competitions), DP optimal solution.
Again, the edge weight is 1, BFS.
Then I took a look at tutorial. That's the good guy.
The only thing I didn't expect was to prove optimization.
If the direct BFS would be nm, this is unacceptable.
#include<bits/stdc++.h> using namespace std; int n, m; #define x first #define y second typedef pair<int, int> comb; comb norm(const comb& a) { return make_pair(min(a.x, n), min(a.y, m)); } bool good(const comb& a) { return a.x == n || a.y == m; } bool comp(const comb& a, const comb& b) { if(a.x != b.x) return a.x > b.x; return a.y > b.y; } int main() { scanf("%d %d", &n, &m); int v; scanf("%d", &v); set<comb> s; for(int i = 0; i < v; i++) { int x, y; scanf("%d %d", &x, &y); s.insert(make_pair(x, y)); } int steps = 0; vector<comb> cur; cur.push_back(make_pair(1, 1)); while(true) { if(cur[0] == make_pair(n, m)) break; vector<comb> ncur; for(auto x : cur) { int sum = x.x + x.y; if(s.count(x)) sum++; comb z = x; z.x = sum; ncur.push_back(norm(z)); z = x; z.y = sum; ncur.push_back(norm(z)); } sort(ncur.begin(), ncur.end(), comp); int mx = 0; vector<comb> ncur2; for(auto x : ncur) { if(x.y <= mx) continue; mx = max(mx, x.y); ncur2.push_back(x); } cur = ncur2; steps++; } printf("%d\n", steps); } #include <bits/stdc++.h> using namespace std; const int LOG = 30; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; int q; cin >> q; vector<int> a(q), b(q); for (int i = 0; i < q; i++){ cin >> a[i] >> b[i]; a[i]--; b[i]--; } if (n > m){ swap(n, m); for (int i = 0; i < q; i++){ swap(a[i], b[i]); } } set<pair<int, int>> st; for (int i = 0; i < q; i++){ st.insert(make_pair(a[i], b[i])); } vector<int> dp(n, -1); dp[0] = 0; int ans = 0; while (true){ ans++; vector<int> dp2(n, -1); for (int i = 0; i < n; i++){ if (dp[i] != -1){ if (st.count(make_pair(i, dp[i])) == 0){ int x = min(i + dp[i] + 1, m - 1); dp2[i] = max(dp2[i], x); int y = min(i + dp[i] + 1, n - 1); dp2[y] = max(dp2[y], dp[i]); } else { int x = min(i + dp[i] + 2, m - 1); dp2[i] = max(dp2[i], x); int y = min(i + dp[i] + 2, n - 1); dp2[y] = max(dp2[y], dp[i]); } } } if (dp2[n - 1] == m - 1){ cout << ans << endl; break; } swap(dp, dp2); } } #include<cstdio> #include<cstring> #include<algorithm> #include<set> #include<map> using namespace std; set<pair<int,int> > st; int n,m,q; inline int query(int u,int v) { return u+v+(st.find(make_pair(u,v))!=st.end()); } int G(int x,int y) { x=min(x,n),y=min(y,m); if(x==n&&y==m) return 0; int q=query(x,y); if(x==n) return G(x,q)+1; if(y==m) return G(q,y)+1; if(x>y) return G(x,q)+1; return G(q,y)+1; } int F(int x,int y) { x=min(x,n),y=min(y,m); if(x==n&&y==m) return 0; int q=query(x,y),ans=0; if(x==n) return F(x,q)+1; if(y==m) return F(q,y)+1; if(x>y) { ans=F(x,q); if(x-y<=5) ans=min(ans,F(q,y)); else ans=min(ans,G(q,y)); return ans+1; } else { ans=F(q,y); if(y-x<=5) ans=min(ans,F(x,q)); else ans=min(ans,G(x,q)); return ans+1; } } int main() { scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=q;i++) { int u,v; scanf("%d%d",&u,&v); st.insert(make_pair(u,v)); } printf("%d\n",F(1,1)); return 0; }
G. Max Sum Array
https://codeforces.com/contest/1612/problem/G
Consider the contributions of the outermost two. Finish one group at a time, cut off the front suffix and continue.
Here are some proofs
#include<bits/stdc++.h> #define rep(i,l,r) for(int i=int(l);i<int(r);i++) #define rep2(i,l,r) for(int i=int(l);i>int(r);i--) #define x first #define y second using namespace std; typedef long long ll; typedef pair<int,int> PII; const int N=1e6+52,mod=1e9+7; 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) { rep(i, 0, sz(v)) { if(i) out << " "; out << v[i]; } return out; } ll m; ll fact[N],cnt[N]; ll total,ans_sum,ans_num=1; void init() { fact[0]=1; for(int i=1;i<N;i++) fact[i]=fact[i-1]*1ll%mod*i%mod; } int main() { init(); scanf("%lld",&m); rep(i,0,m) { ll x;scanf("%lld",&x); cnt[x]++;total+=x; } rep2(i,N-50,1)//Shaping overflow { ans_num=(ans_num%mod*(fact[cnt[i]]%mod*fact[cnt[i]]%mod)%mod)%mod; ans_sum=(ans_sum +(((i - 1)*cnt[i]%mod)*((total - cnt[i]) % mod)%mod))%mod; total-=2*cnt[i],cnt[i-2]+=cnt[i]; } ans_num=(ans_num*fact[cnt[1]])%mod; cout<<ans_sum<<" "<<ans_num<<'\n'; return 0; }
Here's what the boss thinks
Here is a slightly different approach for problem G which I think is easier. (Sorry if my explanation is not good.) It would seem that many other people have this approach too.
First, let's ask ourselves, given an array, how can we find the total sum of distances between all pairs of equal elements? For each element, we will need to add to the answer the sum of absolute values between each pair of indexes where it exists. This is a very well known problem, and can be easily understood by looking at an example.
Let's say an element exists at the indices [1,4,5,6,8][1,4,5,6,8]. Then, we will need to add (4−1)+(5−1)+(6−1)+(8−1)+(5−4)+(6−4)+(8−4)+(6−5)+(8−5)+(8−6)(4−1)+(5−1)+(6−1)+(8−1)+(5−4)+(6−4)+(8−4)+(6−5)+(8−5)+(8−6) to the answer. Overall, 1 has been subtracted 4 times, 4 has been subtracted twice, 5 does not contribute towards the sum, 6 is added twice, and 8 is added 4 times. So we will add to the sum (−4)∗1+(−2)∗4+(0)∗5+(2)∗6+(4)∗8(−4)∗1+(−2)∗4+(0)∗5+(2)∗6+(4)∗8. In general, for a sorted array [p1,p2,...,px][p1,p2,...,px], we will add to the answer p1∗(1−x)+p2∗(3−x)+p3∗(5−x)+...+px∗(x−1)p1∗(1−x)+p2∗(3−x)+p3∗(5−x)+...+px∗(x−1). We can think of this as assigning multiplying each index by a coefficient and finding the total sum of indexes, such that the coefficients assigned to indexes with the same element are a [1−x,3−x,...,x−1][1−x,3−x,...,x−1] in ascending order.
We can now move on to maximising the answer. We will generate a coefficient array. For each cici, we will add the elements [1−ci,3−ci,...,ci−1][1−ci,3−ci,...,ci−1] to the coefficient array. Then, we want to obtain a permutation of this coefficient array [p1,p2,...,pn][p1,p2,...,pn] such that ∑ni=1ipi∑i=1nipi is maximised. By the rearrangement theorem, this sum is maximised when pp is sorted, and it is easy to see that such a permutation is possible.
For more clarity, consider the case where c=[3,3,2]c=[3,3,2]. We will generate the coefficient array [−2,0,2]+[−2,0,2]+[−1,1]=[−2,−2,−1,0,0,1,2,2][−2,0,2]+[−2,0,2]+[−1,1]=[−2,−2,−1,0,0,1,2,2]. Then the maximum answer will be (−2)∗0+(−2)∗1+(−1)∗2+(0)∗3+(0)∗4+(1)∗5+(2)∗6+(2)∗7=27(−2)∗0+(−2)∗1+(−1)∗2+(0)∗3+(0)∗4+(1)∗5+(2)∗6+(2)∗7=27, and this is achievable for example by choosing a=[1,2,3,1,2,3,1,2]a=[1,2,3,1,2,3,1,2].
Now, how do we do this fast? Instead of actually generating the coefficient array, we will simply create a frequency map storing how many times each element exists in the coefficient array. We can create this map quickly using a difference array (or you can visualise this as a sweepline). We will then iterate through this map in ascending order. For each element ee which occurs numnum times in the coefficient array, we will assign ee as the coefficient of the numnum lowest indexes which we haven't assigned yet, and increment our answer by (e∗e∗ sum of chosen indexes). Remember that of the distinct elements in aa, exactly numnum of these elements will have contributed ee to the coefficient array, so these indexes will correspond to some permutation of these numnum elements in aa. We will therefore multiply the number of possible arrays by num!num!, as this is the number of permutation of these numnum elements in aa.
See https://codeforces.com/contest/1612/submission/136599117 for implementation details. If an array is used instead of a map, the overall complexity of this algorithm is O(m+max(ci))O(m+max(ci)).