Hope you all enjoyed SPC Prelims :). Here is the editorial!
A. CPL auction
Is the initial non-zero value of any player, required to find the answer?
To find the final answer is it necessary to find the sum of values of players on day $$$p$$$ and then subtract it with the sum of values of players on initial day.
Every non-zero valued player will contribute 4 crore (that is, by adding 2 crore to the left of him and 2 to his right) each day except the players at the extreme where they only contribute 2 crore.
So we just need to find the number of days it takes for each player so that his value reaches non-zero by using two pointers. With this information we can find the number of days he will contributing by just subtracting days_to_nonzero with $$$p$$$ (If days become negative, make it zero). Now for extreme player multiply this value with 2 and for other players multiply with 4 and finally sum all these to get the final answer.
//Juswanth T
#include <bits/stdc++.h>
using namespace std;
void solve(){
long long int n,p;cin>>n>>p;
vector <long long int> array(n);
vector <long long int> days_to_nonzero(n);
vector <long long int> pointer;
pointer.push_back(LLONG_MIN/2);
for (long long int i=0;i<n;i++){
cin>>array[i];
if (array[i]!=0){
pointer.push_back(i);
}
}
pointer.push_back(LLONG_MAX/2);
long long int c =0;
for (long long int i=0;i<n;i++){
long long int l = pointer[c];
long long int r = pointer [c+1];
days_to_nonzero[i] = min(i-l,r-i);
if ( i == pointer[c+1] ) c++;
}
long long int ans=0;
long long int positive_days_contri;
for (long long int i =0 ;i<n;i++){
long long int days_contributing = p - days_to_nonzero[i];
if (days_contributing>=0 ) positive_days_contri = days_contributing;
else positive_days_contri =0;
if (i == 0 || i==n-1) ans+= 2*positive_days_contri;
else ans += 4*positive_days_contri;
}
if (n== 1) cout<<0<<endl;
else cout<<ans<<endl;
}
int main(){
int t;cin>>t;
while(t--){
solve();
}
}
B. Sponsor
Given the values of the number of Instagram followers of each team, $$$f(a_1,a_2,..,a_i) \oplus f(b_1,b_2,..,b_{n-i})$$$ is fixed and equal to $$$(c_1 \oplus c_2 \oplus .. c_n)$$$
Let's say $$$X = f(a_1,a_2,..,a_i)$$$ $$$Y = f(b_1,b_2,..,b_{n-i})$$$ $$$Z = c_1 \oplus c_2 \oplus .. c_n$$$ so, the equation in Hint-1, becomes $$$X \oplus Y$$$ = $$$Z$$$ If $$$i^{th}$$$ bit of $$$Z$$$ is 1, can we remove such $$$i^{th}$$$ bits(make them zero) of every element in the array? In other words, can we remove all the odd occurrences of 1? Yes, but we have to add $$$Z$$$ to the answer at the end. Because the bits with odd occurrences of 1 contribute the same irrespective of the teams, we choose. so now, can you see that $$$X$$$ = $$$Y$$$? because the occurrence of $$$1$$$ in $$$i^{th}$$$ bit of the elements given is even(now). So, if you pick any values of your choice,$$$X$$$ = $$$Y$$$ holds. Now your task is to find the maximum XOR subset
/**
Shashank Reddy
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fr(i, l, r) for(int i = int(l); i<int(r); ++i)
#define sz(a) int((a.size()))
#define mod 998244353
#define MOD 1e9+7
#define INF 1000000000000000000
int maxSubsetXOR(int set[], int n)
{
//gfg template XD
int index = 0;
for (int i = 60; i >= 0; i--)
{
int maxInd = index;
int maxEle = -1;
for (int j = index; j < n; j++)
{
if ( (set[j] & (1LL << i)) != 0
&& set[j] > maxEle )
maxEle = set[j], maxInd = j;
}
if (maxEle == -1)
continue;
int temp = set[maxInd];
set[maxInd] = set[index];
set[index] = temp;
maxInd = index;
for (int j=0; j<n; j++)
{
if (j != maxInd &&
(set[j] & (1LL << i)) != 0)
set[j] = set[j] ^ set[maxInd];
}
index++;
}
int res = 0;
for (int i = 0; i < n; i++)
res ^= set[i];
return res;
}
void solve()
{
int n;
cin>>n;
int a[n] = {0};
for(int i=0; i<n; ++i) cin>>a[i];
int z = 0;
for(int i=0; i<n; ++i) z ^= a[i];
for(int i=0; i<n; ++i)
{
int temp = ~z;
a[i] &= temp;
}
int ans = maxSubsetXOR(a,n);
cout<<2*ans+z<<endl;
}
int32_t main()
{
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int tc=1; //cin>>tc;
for(int i=1; i<=tc; ++i)
{
solve();
}
}
C. Weird Vendors
Can you find the maximum number of operations required?
If we replace more than we add(replace from another value), the sequence shrinks, which is impossible. The answer to the problem is the number of times we have to add numbers, "completing" the numbers that we chose to be in the final good sequence. So do you think this can be done using something similar like Knapsack?
Let's first consider that the frequency of every number in the sequence given is not more than its value. The sequence's range of numbers is $$$[1,100]$$$. After you find the frequency of each number from $$$1$$$ to $$$100$$$, we don't have to care about values with frequency $$$0$$$. Now for the values with positive frequency, we have two options: keep them or replace them.
So if $$$i$$$ has to be in the final sequence, then we have to do $$$i-freq[i]$$$ operations(either by adding $$$i$$$ to the sequence or replacing some other value with $$$i$$$). So the answer is the number of operations required is the sum of ($$$i-freq[i]$$$), where $$$i$$$ = {set of numbers in the final sequence}.
Now, if the frequency of a number is greater than its value, now we have two options :D Replace all the occurrences of it by some other values[that we keep in the final sequence] or replace $$$freq[i]-i$$$ values of $$$i$$$ with some other values[that we keep in the final sequence]
Now we have to minimize the number of operations. Do you have any thoughts? Let's create an array $$$dp$$$ of size maximum operations+1. And initially set to $$$-1$$$. dp[i] stores the highest sum of a subset of replace_it[j] where the sum of the corresponding keep_it[j]'s is equal to i (please have a look at the code)
/**
Shashank Reddy
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fr(i, l, r) for(int i = int(l); i<int(r); ++i)
#define sz(a) int((a.size()))
#define mod 998244353
#define MOD 1e9+7
#define INF 1000000000000000000
void solve()
{
int n;
cin>>n;
int a[n] = {0};
int freq[101] = {0};
for(int i=0; i<n; ++i)
{
cin>>a[i];
freq[a[i]]++;
}
vector<int> keep_it;
vector<int> replace_it;
int max_op = 0;
for(int i=1; i<101; ++i)
{
if(freq[i]>0)
{
if(freq[i]>i)
{
keep_it.push_back(0);
replace_it.push_back(i);
}
else
{
max_op += (i-freq[i]);
keep_it.push_back(i-freq[i]);
replace_it.push_back(freq[i]);
}
}
}
vector<int> dp(max_op+1,-1);
dp[0] = 0;
for(int i=0; i<keep_it.size(); ++i)
{
int x = keep_it[i];
for(int j = max_op; j>=x; --j)
{
if(dp[j-x]!=-1)
{
dp[j] = max(dp[j-x]+replace_it[i], dp[j]);
}
}
}
for(int i=0; i<=max_op; ++i)
{
if(dp[i]!=-1 && n-dp[i]<=i)
{
cout<<i<<endl;
return;
}
}
cout<<-1<<endl;
}
int32_t main()
{
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int tc=1; cin>>tc;
for(int i=1; i<=tc; ++i)
{
solve();
}
}
D. Meet the Squad
First check if there are atleast $$$p-2$$$ different colours in the audience array, if not immediately the output will be 0 else proceed further. Create two pointers 'left' and 'right' as well as a frequency array for colours.
Traverse through the audience array using the pointers by increasing and decreasing the window ( the set of audiences contained within the pointers) size with the help of 'right' and 'left' respectively. If at any point the number of distinct colours within the pointer window exceeds $$$p-2$$$, start shrinking the window from left untill it becomes equal to $$$p-2$$$. Keep track of the maximum value of number of audience in the window with $$$p-2$$$ distinct colour and atleast one yellow colour shirt till the current phase. Finally maximum of that value will be the answer once the array is completely traversed.
// Juswanth T
#include <bits/stdc++.h>
using namespace std;
void solve(){
int n,p;
cin>>n>>p;
vector <int> crowd(n);
set <int> distinct;
map <int,int> freq;
for (int i=0;i<n;i++) {
cin>>crowd[i];
distinct.insert(crowd[i]);}
if (p-2> distinct.size()) cout<<0<<endl;
else {
int left = 0; int maxx =0; int uniq =0;
for (int right =0 ;right<n;right++){
if (freq[crowd[right]] == 0) uniq++;
freq[crowd[right]]++;
while (uniq> p-2){
freq[crowd[left]]--;
if (freq[crowd[left]]==0) uniq--;
left++;
}
if (freq[1]!=0) maxx = max(maxx,right -left +1);
}
cout<<maxx<<endl;
}
}
int main(){
int t;cin>>t;
while(t--){
solve();
}
}
E. Jersey
The first hint is already given in the problem statement :-)
You can iterate through the prices at each outlet, and if for any value it satisfies $$$a_i \leq m$$$, the answer is "YES". Else the answer is "NO".
Alternatively, you can sort the array, and if the minimum element is higher than $$$m$$$, the answer is "NO", else the answer is "YES".
/**
Shashank Reddy
*/
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n,m;
cin>>n>>m;
int x; int flag = 0;
for(int i=0; i<n; ++i)
{
cin>>x;
if(x<=m) flag = 1;
}
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
int32_t main()
{
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int tc=1; cin>>tc;
for(int i=1; i<=tc; ++i)
{
solve();
}
}
F. Help Pishabh Rant
Use dfs graph algorithm to traverse across all the nodes. From each node, find number of 'C' and number of 'L' in its subtree. If at any point there were all the 'L' and no 'C' or all 'C' and no 'L' in a subtree, then increment the answer by 1 . Once dfs recursion is over, final answer (after all the incrementation) will the number of edges with the given condition.
// Juswanth T
#include <bits/stdc++.h>
using namespace std;
int ans =0,totalC =0,totalL=0;
vector<int> tree[100005],countC(100005,0),countL(100005,0);
vector<char> support(100005);
void dfs (int current, int parent){
if (support[current]=='C') countC[current]=1;
else if (support[current]=='L') countL[current]=1;
for (auto child:tree[current]){
if (child==parent) continue;
dfs(child,current);
countC[current]+=countC[child];
countL[current]+=countL[child];
}
if (countC[current] == totalC && countL[current] == 0) ans++;
else if (countC[current] == 0 && countL[current] == totalL) ans++;
}
void solve(){
int n;
cin>>n;
for (int i=0;i<n-1;i++){
int u,v;
cin>>u>>v;
tree[u].push_back(v);
tree[v].push_back(u);
}
for (int i=1; i<=n; i++){
cin>>support[i];
if (support[i]=='C') totalC++;
else if (support[i]=='L') totalL++;
}
dfs(1,0);
cout<<ans<<endl;
}
int main(){
solve();
}
G. Password
Can you see a pattern? When the length of the string is an even number, you can find the answer for the string without the last character and add it at the end.
Now consider the case when the length of the string is odd. Observe the pattern when the string length is $$$(4n+1)$$$ and $$$(4n+3)$$$. $$$abc$$$ -> $$$cba$$$, $$$abcde$$$ -> $$$edabc$$$, $$$abcdefg$$$ -> $$$gfcbade$$$, $$$abcdefgh$$$ -> $$$ihedabcfg$$$
/**
Shashank7704
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
void process_string(string s, int n)
{
int t = (n)%4;
for(int i=(n-1); i>=4; i-=4)
{
cout<<s[i]<<s[i-1];
}
int k;
if(t==1)
{
cout<<s[0]<<s[1]<<s[2];
k = 5;
}
else
{
cout<<s[2]<<s[1]<<s[0];
k = 3;
}
for(int i=k; i<=(n-2); i+=4)
{
cout<<s[i]<<s[i+1];
}
}
void solve()
{
int n;
cin>>n;
string s;
cin>>s;
if(n==1 || n==2)
{
cout<<s<<endl;
}
else if(n%2==0)
{
process_string(s, n-1);
cout<<s[n-1]<<endl;
}
else
{
process_string(s, n);
cout<<endl;
}
}
int32_t main()
{
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t=1;
cin>>t;
for(int i=1; i<=t; ++i)
{
solve();
}
return 0;
}
H. Final Match
Is this problem related to the of divisors of $$$n$$$? say $$$d$$$ is a divisor of $$$n$$$ and if the string $$$s$$$ can be represented as a repeating sequence of length $$$d$$$. Then $$$d$$$ is the period of $$$s$$$. Let's define the magic number of strings = minimum period $$$d$$$ of the string.
For example, the magic number of the string "abcabcabc" = 3.
suppose if a string $$$s$$$ is a palindrome, with magic number $$$d$$$. Then string containing the first $$$d$$$ characters of $$$s$$$ is also a palindrome?
For example, "abaabaaba" has a magic number = $$$3$$$, and "aba" is also a palindrome.
Create an array of size equal to the number of divisors of $$$n$$$. Let divisors[n] be the array that stores the divisors of $$$n$$$ in increasing order. Let's say $$$dp[i]$$$ denotes the number of strings that are palindromes that can be created using the characters from the set $$$S$$$, whose size is $$$k$$$, and the magic number of the string is equal to $$$(i+1)^{th}$$$ divisor of $$$n$$$. Now $$$dp[i]$$$ = $$$k^{\lceil d/2 \rceil}$$$-$$$\sum_{x}^{divisor[i]}dp[x]$$$(here x are divisors of divisor[i] and x is not equal to divisor[i]) now consider twos cases when divisor[i] is odd and divisor[i] is even. So is the answer $$$\sum{divisor[i]dp[x]}$$$? No, some strings do repeat, when $$$divisor[i]$$$ is even if you rotate to the left by $$$t$$$ characters and if you rotate to the right by $$$divisor[i]-t$$$ then both would result the same string. So the answer is $$$\sum{divisor[i]dp[x]}$$$(divisor[i] is odd)+$$$\sum{(divisor[j]dp[x])/2}$$$(divisor[j] is even)
/**
Shashank Reddy
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fr(i, l, r) for(int i = int(l); i<int(r); ++i)
#define sz(a) int((a.size()))
//#define mod 998244353
#define mod 1000000007
#define INF 1000000000000000000
int fast_mutiplier(int a, int b)
{
int result = 1;
int a_p = a%mod; //a_p holds a^(2^i)
while(b!=0)
{
if(b%2==1)
{
result = ((result%mod)*a_p)%mod;
}
a_p = (a_p*a_p)%mod;
b = b/2;
}
return result;
}
void solve()
{
int n, k;
cin>>n>>k;
vector<int> divisors;
for(int i=1; i*i<=n; ++i){
if(n%i==0) {
if(n/i==i) {
divisors.push_back(i);
}
else{
divisors.push_back(i);
divisors.push_back(n/i);
}
}
}
sort(divisors.begin(),divisors.end());
int ans = 0;
int dp[divisors.size()+1];
for(int i=0; i<divisors.size(); ++i){
dp[i] = fast_mutiplier(k, divisors[i]/2+divisors[i]%2);
for(int j=0; j<i; ++j)
{
if(divisors[i]%divisors[j]==0)
{
dp[i] -= dp[j];
dp[i] += mod;
dp[i] %= mod;
}
}
if(divisors[i]%2==1){
ans += ((divisors[i])*dp[i])%mod;
}
else
{
ans += ((divisors[i]/2)*dp[i])%mod;
}
ans = ans%mod;
}
cout<<(ans+mod)%mod<<endl;
}
int32_t main()
{
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int tc=1; //cin>>tc;
for(int i=1; i<=tc; ++i)
{
solve();
}
}
I. Fours and Sixers
Consider the binary form of $$$x$$$ and $$$y$$$. The analysis of all possible cases is given below
Representation $$$\binom{m}{n}_{p,q}$$$ :It means if $$$m$$$ is any bit of $$$p$$$ then its corresponding bit in $$$q$$$ will be $$$n$$$.
Case 1: $$$\binom{1}{0}_{x,y}$$$ − In this case we can′ t find a valid bit corresponding to a and b.
Case 2: $$$\binom{0}{0}_{x,y}$$$ − In this case the only possible combination of bit for a and b is $$$\binom{0}{0}_{a,b}$$$.
Case 3: $$$\binom{0}{1}_{x,y}$$$ − In this case the only possible combination of bit for a and b is $$$\binom{1}{1}_{a,b}$$$.
Case 4: $$$\binom{1}{1}_{x,y}$$$ − Two possibility arises in this case $$$\binom{0}{1}_{a,b}$$$ and $$$\binom{1}{0}_{a,b}$$$ .
So first check for case I by using the condition $$$x$$$& ~$$$y$$$≠$$$0$$$ If it′s satisfied then case I exist hence our answer will be directly −1 else follow the further procedure. Whenever case 4 arises take $$$\binom{1}{0}_{a,b}$$$ and ignore the other as we need to maximize a. For case 2 and 3 since there is only one possibility for each, we should go with it. By considering all these cases we can come to a conclusion that the maximum possible value of a will be y itself and the corresponding value of b is $$$x$$$^$$$y$$$ .
Ex : Take $$$x = 20$$$ and $$$y = 30$$$, Their binary representation will be
$$$x = 1 0 1 0 0$$$ --------------- $$$a = n 1 m 1 0$$$
$$$y = 1 1 1 1 0$$$ --------------- $$$b = n' 1 m' 1 0$$$
During case 4 in order to maximize $$$a$$$, $$$n$$$ should 1 and for the same reasoning $$$m$$$ should also be 1. This makes the binary representation of $$$a$$$ and $$$b$$$ to be,
$$$a = 1 1 1 1 0$$$
$$$b = 0 1 0 1 0$$$
// Juswanth T
#include <bits/stdc++.h>
using namespace std;
void solve(){
int x,y;
cin>>x>>y;
if ((x&~y) != 0) cout<<-1<<endl;
else {
int a = y; int b = x^y;
cout <<a<<" "<<b<<endl;
}
}
int main(){
int t;cin>>t;
while(t--){
solve();
}
}