1934A — Слишком Мин Слишком Макс
Каким был бы ответ, если бы в массиве было только 4 элемента?
Предположим, что в массиве только 4 элемента. Назовем их $$$a \leq b \leq c \leq d$$$. Тогда ответом был бы максимум среди 3 вариантов, которые приведены ниже:
явно максимумом является $$$2*(d+c)-2*(a+b)$$$.
Соответственно, чтобы максимизировать ответ, нам нужно сделать $$$d$$$ и $$$c$$$ как можно больше и $$$a$$$ и $$$b$$$ как можно меньше. Мы можем этого добиться выставив $$$d=a_n$$$, $$$c=a_{n-1}$$$, $$$b=a_{2}$$$ и $$$a=a_{1}$$$ где $$$a_i$$$ обозначает $$$i$$$-й элемент в отсортированном массиве.
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int testcases;
cin >> testcases;
for (int t = 1; t <= testcases; t++)
{
int n;
cin >> n;
vector<int> v(n);
for (int j = 0; j < n; j++)
{
cin >> v[j];
}
sort(v.begin(), v.end());
cout << 2 * (v[n - 1] - v[0]) + 2 * (v[n - 2] - v[1]) << endl;
}
}
t = int(input())
for i in range(t):
n = int(input())
a = list(map(int, input().split()))
a = sorted(a)
ans = 2 * (a[n - 1] - a[0] + a[n - 2] - a[1])
print(ans)
1934B — Еще одна задача о монетах
Как много монет стоимости $$$1$$$, $$$3$$$, $$$6$$$, $$$10$$$ может потребоваться?
Факт: Вам не потребуется больше $$$2$$$ единиц, $$$4$$$ троек, $$$4$$$ шестерок и $$$2$$$ десяток.
Объяснение:
Для $$$1$$$: Предположим, что вы используете $$$k > 2$$$ единиц, тогда вы можете использовать одну тройку и $$$k - 3$$$ единиц.
Для $$$3$$$: Предположим, что вы используете $$$k > 1$$$ тройки, тогда вы можете использовать одну шестерку и $$$k - 2$$$ тройки.
Для $$$6$$$: Предположим, что вы используете $$$k > 4$$$ шестерок, тогда вы можете использовать две монеты стоимости пятнадцать и $$$k - 5$$$ шестерок.
Для $$$10$$$: Предположим, что вы используете $$$k > 2$$$ десяток, тогда вы можете использовать две монеты стоимости пятнадцать и $$$k - 3$$$ десяток.
И поскольку ограничение на количество этих монет достаточно маленькое, мы можем перебрать, сколько их будет, заполнив все остальное монетами стоимости 15.
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int testcases;
cin >> testcases;
for (int t = 1; t <= testcases; t++)
{
int n;
cin >> n;
int ans = 1e9;
for(int ones = 0; ones <= 2; ones++){
for(int threes = 0; threes <= 1; threes++){
for(int sixes = 0; sixes <= 4; sixes++){
for(int tens = 0; tens <= 2; tens++){
int brute_sum = 1*ones + 3*threes + 6*sixes + 10*tens;
if(brute_sum <= n && (n-brute_sum)%15 == 0){
ans = min(ans, ones + threes + sixes + tens + (n-brute_sum)/15);
}
}
}
}
}
cout << ans << endl;
}
}
Когда жадная логика выбора самой дорогой монеты до упора будет работать?
Факт $$$1$$$: Если бы мы имели только монеты стоимости $$$1$$$, $$$3$$$, $$$6$$$ и $$$15$$$, жадная логика выбора самой дорогой монеты до упора работала бы.
Факт $$$2$$$: Нам не нужно больше $$$2$$$ монет стоимости десять.
Объяснение: Лучше использовать $$$2$$$ монеты стоимости пятнадцать вместо $$$3$$$ монет стоимости десять.
Используя два факта выше, можно показать, что, ответ будет равен $$$\min(\text{ans}(n-10*k)+k$$$) для $$$k \leq 2$$$, при гипотезе использония только монет стоимости $$$1$$$, $$$3$$$, $$$6$$$ и $$$15$$$ для вычисления жадного $$$\text{ans}(x)$$$.
#include<bits/stdc++.h>
using namespace std;
int getAns(int n){
int ans=0;
ans+=n/15;
n%=15;
ans+=n/6;
n%=6;
ans+=n/3;
n%=3;
ans+=n;
return ans;
}
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr);
int testcases;
cin>>testcases;
for(int i=1;i<=testcases;i++){
int n;cin>>n;
if(n<10){
cout<<getAns(n)<<endl;
}else if(n<20){
cout<<min(getAns(n),getAns(n-10)+1)<<endl;
}else{
cout<<min({getAns(n),getAns(n-10)+1,getAns(n-20)+2})<<endl;
}
}
}
Что мы знаем о расположении мин, если мы сделаем запрос "? 1 1"?
Пусть ответ $$$a_1$$$, тогда локацией одной из мин будет $$$(x, y)$$$, где $$$x+y = a_1+2$$$.
Можем ли мы найти мину, сделав запросы к обоих концам диагонали $$$x+y=a_1+2$$$?
Сначала сделаем запрос "? 1 1". Получим ответ $$$a_1$$$, и узнаем, что локацией одной из мин будет $$$(x, y)$$$, где $$$x+y = a_1+2$$$.
Теперь сделаем еще два запроса к обоим концам этой диагонали. После этих запросов мы получим две гипотетические локации для мины, которая расположена на этой диагонали. Спросим одну из них. Если мы получим $$$0$$$, то мы явно нашли мину, иначе мы можем быть уверены, что альтернативная локация содержит мину.
Объяснение: На этой диагонали располагается некоторая мина, есть расстояние от нее до каждого из концов диагонали. Когда мы делаем запрос к концам диагонали, мы получаем либо расстояние до этой мины, либо меньшее расстояние до другой мины. Другая мина не могла уменьшить ответ для обоих концов, поскольку тогда бы получалось, что путь от одного конца диагонали до другого через другую мину, короче расстояния по диагонали, что невозможно, ибо оно и так самое короткое.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll query(ll x, ll y) {
cout << "? " << x << ' ' << y << endl;
ll d;
cin >> d;
return d;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
ll t;
cin >> t;
while (t--) {
ll n, m;
cin >> n >> m;
ll sum1 = query(1, 1) + 2;
ll sum2 = n + m - query(n, m);
ll dif1 = query(1, m) + 1 - m;
auto simplify = [&](ll num, ll lim)->ll{
return max(min(num, lim), 1LL);
};
ll x1 = simplify((sum1+dif1)/2, n), y1 = simplify((sum1-dif1)/2, m);
ll x2 = simplify((sum2+dif1)/2, n), y2 = simplify((sum2-dif1)/2, m);
if (query(x1, y1)) cout << "! " << x2 << ' ' << y2 << endl;
else cout << "! " << x1 << ' ' << y1 << endl;
}
return 0;
}
Что если вторым запросом мы спросим "? n m"?
Пусть ответ $$$a_2$$$, тогда локацией второй мины будет $$$(x, y)$$$, где $$$x+y = n+m-a_2$$$.
Используя Подсказку 1 и Подсказку 2, если мы получили одну и ту же диагональ, т.е. $$$n+m-a_2=a_1-2$$$, мы можем просто сделать запрос к одному из концов этой диагонали и явно получить ответ.
Иначе, давайте сделаем запрос "? 1 m". Тогда мы узнаем еще одну диагональ, которая перпендикулярна двум предыдущим. Она пересекает по двум точкам две предыдущие диагонали, соответсвенно одна из них точно содержит мину.
Спросим одну из них. Если мы получим $$$0$$$, то мы явно нашли мину, иначе мы можем быть уверены, что альтернативная локация содержит мину.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll query(ll x, ll y) {
cout << "? " << x << ' ' << y << endl;
ll d;
cin >> d;
return d;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
ll t;
cin >> t;
while (t--) {
ll n, m;
cin >> n >> m;
ll sum1 = query(1, 1) + 2;
ll sum2 = n + m - query(n, m);
ll dif1 = query(1, m) + 1 - m;
auto simplify = [&](ll num, ll lim)->ll{
return max(min(num, lim), 1LL);
};
ll x1 = simplify((sum1+dif1)/2, n), y1 = simplify((sum1-dif1)/2, m);
ll x2 = simplify((sum2+dif1)/2, n), y2 = simplify((sum2-dif1)/2, m);
if (query(x1, y1)) cout << "! " << x2 << ' ' << y2 << endl;
else cout << "! " << x1 << ' ' << y1 << endl;
}
return 0;
}
1934D1 — Разбиение XOR — сольная версия
Для получение любого достижимого $$$m$$$ достаточно двух операций.
Давайте определим все достижимые $$$m$$$ для данного $$$n$$$.
Если $$$n$$$ является степенью $$$2$$$-ки, тогда мы не можем его разбить, соответственно, не существует никаких достижимых $$$m < n$$$. Иначе, если $$$n$$$ содержит хотя бы два единичных бита, давайте обозначим старший единичный бит как $$$a$$$, и второй старший единичный бит как $$$b$$$. То есть $$$n = 2^a + 2 ^ b + r$$$, где $$$r < 2 ^ b$$$, $$$a > b$$$.
Факт 1: Все значения $$$m$$$ меньшие $$$n$$$ достижимы, если их старший единичный бит не лежит между $$$b+1$$$ и $$$a-1$$$.
Пример: К примеру, $$$1001????$$$ может быть разбито на $$$1000????$$$ и $$$0001????$$$, или $$$1001????$$$ и $$$0000????$$$. При любом раскладе мы не может изменить $$$6$$$-й и $$$7$$$-й биты.
Используя эти факты, мы можем разбить задачу на два случая:
Случай 1: Если старший единичный бит $$$m$$$ на позиции $$$\leq b$$$.
Выполним первую операцию вида $$$2^{b+1} - 1$$$ и $$$n \oplus (2^{b+1} - 1)$$$ ($$$10001????$$$ -> $$$10000????$$$ и $$$000011111$$$ в бинарном виде). Тогда любая подмаска числа $$$2^{b+1} - 1$$$ ($$$000011111$$$ в бинарном виде) может быть достигнута на следующем шаге.
Случай 2: Если старший единичный бит $$$m$$$ на позиции $$$a$$$.
Если старший единичный бит $$$m$$$ на позиции $$$a$$$, тогда $$$m$$$ может быть достигнута за одну операцию $$$m$$$ и $$$m \oplus n$$$, поскольку $$$m < n$$$ по условию, и $$$n \oplus m$$$ имеет свой старший единичный бит на позиции $$$< a$$$, а значит оно строго меньше $$$n$$$.
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
ll t;
cin >> t;
while (t--) {
ll n, m;
cin >> n >> m;
ll hi = 0, sec_hi = 0;
for (ll p = (1LL<<62); p > 0; p >>= 1) {
if (p & n) {
if (!hi) hi = p;
else if (!sec_hi) sec_hi = p;
}
}
bool flag = (sec_hi && ((m & hi) || (m < sec_hi*2)));
if (!flag) {
cout << -1 << '\n';
continue;
}
vector<ll> ans = {n, m};
if (!(m & hi) && !(m & sec_hi)) ans = {n, m^sec_hi, m};
cout << (ll)ans.size()-1 << '\n';
for (auto &x: ans) cout << x << ' ';
cout << '\n';
}
return 0;
}
1934D2 — Разбиение XOR — игровая версия
Если оба числа $$$p_1$$$ и $$$p_2$$$ являются степенями $$$2$$$, то это проигрышное состояние, поскольку вы не можете провести операцию разбиения ни на одном из них.
Если хотя бы одно из чисел $$$p_1$$$ или $$$p_2$$$ имеет два единичных бита, то это выигрышное состояние.
Вы можете выбрать это число с двумя единичными битами и форсировать оппонента перейти в состояние, описанное в подсказке 1.
Факт 1: Если $$$p_1$$$ имеет нечетное количество единичных битов, тогда оно обязательно будет разбито на два числа, где одно содержит четное количество битов, а другое нечетное.
Факт 2: Если $$$p_1$$$ или $$$p_2$$$ имеет четное количество единичных битов, то оно может быть разбито на два числа с нечетным количество единичных битов.
Объяснение : Пусть этим числом будет $$$p_1$$$. Тогда разобьем его на $$$2^{msb \text{ of } p_1}$$$ и $$$p_1 \oplus 2^{msb \text{ of } p_1}$$$. Где $$$msb$$$ — старший единичный бит.
Если оппонент выбирает $$$2^{msb \text{ of } p_1}$$$, он моментально проигрывает (причина — Подсказка $$$1$$$), поэтому он форсированно выбирают другое число с нечетным количеством битов. Из Факта $$$1$$$ мы можем заключить, что на следующем ходе мы снова сможем выбрать число с нечетным количеством битов.
Поскольку мы каждый раз избавляемся от самого старшего единичного бита, игра продолжится не дольше чем $$$60$$$ ходов игрока, стоящего в выигрышной позиции.
Следовательно, будучи Алисой, мы хотим ходить первыми, если $$$n$$$ имеет четное количество единичных битов, и ходить вторыми, если количество единичных битов нечетно. Будем играть используя стратегию, которая описана выше.
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int testcases;cin>>testcases;
for(int testcase=1;testcase<=testcases;testcase++){
long long n;cin>>n;
long long curr=n;
int parity=0;
if(__builtin_popcountll(n)%2){
cout<<"secoNd"<<endl;
}else{
cout<<"firSt"<<endl;
parity=1;
}
int turn=0;
while(1){
if(turn%2==parity){
long long p1,p2;cin>>p1>>p2;
if (p1 == 0 && p2 == 0)
break;
if(__builtin_popcountll(p1)%2==0){
curr=p1;
}else{
curr=p2;
}
}else{
int pos=0;
for(int i=0;(1ll<<i)<curr;i++){
if(curr&(1ll<<i)){
pos=i;
}
}
long long p1=(1ll<<pos);
long long p2=curr^p1;
cout<<p1<<" "<<p2<<endl;
curr = p1;
}
turn++;
}
}
}
Факт 1: Если для некоторой тройки $$$(x, y, z)$$$ их попарные НОДы равняются их общему НОДу (это значит, что $$$(x, y, z)$$$ = $$$(g * X, g * Y, g * Z)$$$ где $$$(X, Y, Z)$$$ попарно взаимнопросты), тогда применение операции к ним дает $$$(g * X * Y, g * X * Z,g * Y * Z)$$$, и посмотрев на подпоследовательности размера РОВНО 2, мы найдем все три НОДа: $$$x$$$, $$$y$$$, $$$z$$$. Назовем такую тройку КРАСИВОЙ.
Результат: Если мы можем разбить все значение на независимые КРАСИВЫЕ тройки, тогда просто можно применить операцию к каждой из них, и задача решена.
Факт 2: Мы можем совсем не трогать значения $$$\leq \frac{n}{2}$$$. Рассмотрим $$$x \leq \frac{n}{2}$$$, тогда имеется и $$$2 * x \leq n$$$. Если мы не трогаем $$$x$$$ совсем, то мы всегда будем иметь некоторое другое значение, которое делится на $$$x$$$ (легко заметить, что применение операции на таком значении всегда производит хотя бы одно другое значение, которое тоже делится на $$$x$$$), таким образом мы всегда будем иметь НОД равный $$$x$$$, взяв подпоследовательность $$$(x, x * A)$$$.
Факт 3: Последовательные целые числа $$$(x, x+1, x+2, ..., x+11)$$$ можно разбить на $$$4$$$ независимые КРАСИВЫЕ тройки размера $$$3$$$, при условии $$$(x+11) \% 4$$$ равняется $$$2$$$ или $$$1$$$.
Для $$$(x+11) \% 4 = 2$$$: Тройки $$$(x, x+1, x+2)$$$, $$$(x+4, x+5, x+6)$$$ и $$$(x+8, x+9, x+10)$$$ являются КРАСИВЫМИ, первое и третье числа в каждой тройке являются нечетными, второе четным, поэтому их общий и попарные НОДы равны $$$1$$$. Тройка $$$(x+3, x+7, x+11)$$$ является КРАСИВОЙ, ибо она представимы в виде $$$(2*(2*n-1)$$$, $$$2*(2*n)$$$, $$$2*(2*n+1))$$$, соответственно их общий и попарные НОДЫ равны $$$2$$$.
Для $$$(x+11) \% 4 = 1$$$: Тройки $$$(x, x+4, x+8)$$$, $$$(x+1, x+2, x+3)$$$, $$$(x+5, x+6, x+7)$$$ и $$$(x+9, x+10, x+11)$$$ являются КРАСИВЫМИ. Применима та же логика что и для $$$(x+11) \% 4 = 2$$$,
Если $$$n \% 4 = 3$$$, то мы можем выполнить операцию $$$(1, 2, n)$$$, и если $$$n \% 4 = 0$$$ можем выполнить операцию $$$(1, n-1, n)$$$.
Давайте сгруппируем оставшиеся элементы, начиная с конца в группы размера $$$12$$$ пока мы не перескочим ниже $$$\frac{n}{2}$$$.
Итого можно посчитать, что мы использовали не более $$$\lfloor \frac{n}{6} \rfloor + 5$$$ операций.
Решения для $$$n \leq 13$$$ должны быть найдены вручную.
#include<bits/stdc++.h>
using namespace std;
vector<vector<vector<int>>> pans(14);
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr);
int t;cin>>t;
pans[3]={{1,2,3}};
pans[4]={{1,3,4}};
pans[5]={{3,4,5}};
pans[6]={{1,3,5},{2,4,6}};
pans[7]={{2,4,6},{3,5,7}};
pans[8]={{2,6,8},{3,5,7}};
pans[9]={{1,3,5},{2,4,6},{7,8,9}};
pans[10]={{3,4,5},{2,6,8},{7,9,10}};
pans[11]={{2,6,8},{3,5,7},{9,10,11}};
pans[12]={{1,11,12},{6,8,10},{5,7,9}};
pans[13]={{1,12,13},{7,9,11},{6,8,10}};
for(int tt=0;tt<t;tt++){
int n;cin>>n;
if(n<=2){
cout<<-1<<endl;
}else if(n<14){
cout<<pans[n].size()<<endl;
for(auto w: pans[n]){
cout<<w[0]<<" "<<w[1]<<" "<<w[2]<<endl;
}
}else{
vector<int> v(n);
for(int i=0;i<n;i++){
v[i]=i+1;
}
vector<vector<int>> ans;
while (2*v.size()>n){
if(v.size()%4==2){
vector<int> buf;
for(int i=0;i<12;i++){
buf.push_back(v.back());
v.pop_back();
}
reverse(buf.begin(),buf.end());
ans.push_back({buf[0],buf[1],buf[2]});
ans.push_back({buf[4],buf[5],buf[6]});
ans.push_back({buf[8],buf[9],buf[10]});
ans.push_back({buf[3],buf[7],buf[11]});
}else if(v.size()%4==1){
vector<int> buf;
for(int i=0;i<12;i++){
buf.push_back(v.back());
v.pop_back();
}
reverse(buf.begin(),buf.end());
ans.push_back({buf[1],buf[2],buf[3]});
ans.push_back({buf[5],buf[6],buf[7]});
ans.push_back({buf[9],buf[10],buf[11]});
ans.push_back({buf[0],buf[4],buf[8]});
}else if(v.size()%4==3){
vector<int> buf;
buf.push_back(v.back());
v.pop_back();
buf.push_back(2);
buf.push_back(1);
reverse(buf.begin(),buf.end());
ans.push_back({buf[0],buf[1],buf[2]});
}else{
vector<int> buf;
buf.push_back(v.back());
v.pop_back();
buf.push_back(v.back());
v.pop_back();
buf.push_back(1);
reverse(buf.begin(),buf.end());
ans.push_back({buf[0],buf[1],buf[2]});
}
}
cout<<ans.size()<<endl;
for(auto w: ans){
cout<<w[0]<<" "<<w[1]<<" "<<w[2]<<endl;
}
}
}
}
first so ez
Practicing Problem: C
Can you please explain Why my code gave Idleness Time limit exceeded: Submission: https://mirror.codeforces.com/contest/1934/submission/258202514
Idrk how C++ works, sorry brosef. Maybe someone else will be kind enough to help you. Are you properly flushing your output?
This is what I need to know....... :(
You should try to delete "#define endl '\n'".
Yeah, it worked after that. Thanks
Fast editorial!
WHY DOWNWOTE???
Thanks for the fast System test and fast editorial. It was a great contest and I liked problem C. I think every contest needs an interactive problem at least.
wtf! NO. It's cringe.
So you like a mathforces round?
Ironic enough I classify C as a math problem...
How often will interactive tasks appear now? (I just didn’t notice them during the rounds before)
Interactive problems are not much but in last two contests problem C was interactive.
English editorial pls ?
I just refreshed the page and the text changed from English to Russian. Please fix it,thanks.
UPD:It was fixed,thanks!
E: First time a problem need to hardcode from n=3 to n=13
Problem C seems to essentially be a duplicate of a problem which I wrote in a previous DMOJ round, but with one fewer step. This is probably just a coincidence though.
It must be unrated
Nah honestly if you can recall a 1.5 year old problem from memory then you deserve the points.
You would be laughing right before the round I was solving https://mirror.codeforces.com/problemset/problem/1797/C with all logic done, just fixing final bugs. Still I didn't solve C during the round. Although I think I would if hadn't switched to D.
I mean, there's a Div2 Edu E a while ago thzt's literally the hard copy of APIO22 P3, lol
or a problem from 5 years ago
whats the reason behind this?
If coins of value 1, 3, 6 and 15 were only present the greedy logic of selecting the higher valued first would work.
Added the proof. Is it written clearly?
Nice Explanation, Thanks!
This part is trying to prove the greedy method works properly, and I still getting it.
Another solution for B is to do greedy by picking the highest possible denomination each time, but finally decrease the above answer by 0,1 or 2 depending upon the value of n mod 15.
Can you please explain why this works ?
because a_max(highest value) is fixed such the remainders which are 1->14 and there cases
Noticed that when we try to acheive a big n, using as many 15s seems to be right. However, the initial greedy solution may be wrong because in some situations we can take a step back and get a smaller answer.There are only two such situations: when n%15==5(5=1+1+3,20=15+5=10+10) or n%15==8(8=1+1+6,23=15+8=10+10+3).
https://mirror.codeforces.com/contest/1934/submission/249187805 I am not getting why is it giving idleness limit exceeded verdict
because it's wrong
Then why the verdict is not "Wrong Answer"?
PS: downvotes for a doubt. Crazy!
cout.flush() ?
I gave you upvote.
The third test case of $$$D2$$$ really confused me. Why are we moving first, and why is Bob not splitting $$$10$$$ into $$$8$$$ and $$$2$$$, which should be optimal according to Bob?
Also, what is
classic classic
in the input?For $$$D-2$$$, you can also bruteforce/precalculate the states by checking every $$$n$$$ : $$$a$$$, $$$b$$$ transition since $$$n$$$ is atmost $$$60$$$
Problems from this contest made me realize how low my IQ is...
True, I found these thinking problems hard for me as well.
Y'alls IQ higher than mine!
Задача D2.
Как раз наоборот. Мы должны сохранять инвариант, что на нашем ходе всегда четное количество.
E: Are there any cute approach for $$$n$$$ is small?
I used randomized brute force(and easily found a solution, 249183723 (commentout code)), but I'm looking for simpler approach.
This isn't exactly an answer to your question, but I came up with a solution that does not require brute force (but it did require a leap of faith for smaller cases):
The basic idea is exactly as in the editorial, we only care about $$$x > \frac{n}{2}$$$.
We will try to make tuples with these numbers starting from $$$\frac{n+2}{2}$$$, we will only consider consecutive numbers.
Let $$$(x_1, x_1 + 1, x_1 +2)$$$ be the tuple that we are considering in this moment:
If $$$x_1$$$ is odd, then we can apply the operation as in the editorial and continue with the next numbers.
If not, then one of $$$x_1$$$ and $$$x_1+2$$$ is not divisible by $$$4$$$. Let's assume that $$$x_1$$$ satisfies this property. Then we will apply the operation to the tuple $$$(\frac{x_1}{2}, x_1+1, x_1+2)$$$. Notice that $$$\frac{x_1}{2}$$$ was not modified by other operations until now. Now, we can prove that we can generate the values of $$$x_1$$$, $$$x_1+1$$$, $$$x_1+2$$$ and $$$\frac{x_1}{2}$$$ with the new values generated, and $$$x_1$$$, that was not used.
Finally, we have to consider the cases where we didn't handle the last numbers. If only two numbers were left, then the solution is equal to the editorial. But if one number is left, then we will use $$$(n, 1, \text{a number that is coprime with n and was not used})$$$
You have to prove that there will always exist such number, for a big $$$n$$$ is reasonable, but for a small $$$n$$$ I just had faith.
Another approach of B: 2 * max >= 3 * 2nd max i.e. 2 * 15 >= 3 * 10, which means if n >= 30, always better to take 15s until n < 30, then for residual count (max 29), dp can be used.
submission: https://mirror.codeforces.com/contest/1934/submission/249116555
Can someone please explain how the formula was derived in problem A? Like how is |a−b|+|b−c|+|c−d|+|d−a| equal to 2∗d−2∗a? I'll be able to understand the next two if I only knew how to do this :(
When the value in the mod is negative, we negate its contents while removing the mod.
So as stated $$$a \leq b \leq c \leq d$$$, when we open the mods it becomes $$$(-(a-b))+(-(b-c))+(-(c-d))+(d-a)$$$ which on simplifying gives $$$b-a-b+c-c+d+d-a$$$ which equals $$$2*d-2*a$$$
Oh ok I get it. Thanks a lot!
include<bits/stdc++.h> include using namespace std;
void minCoins() { int n; cin>>n; int coins[] = {15, 10, 6, 3, 1}; int min1=INT_MAX, numCoins = 0; for(int i=0;i<5;i++){ if((n%coins[i])==0) min1=min(min1,n/coins[i]); } for (int i = 0; i < 5; i++) { numCoins += n / coins[i]; n %= coins[i]; }
cout<<min(min1,numCoins)<<endl; }
int main() { int t; cin >> t; while (t--) { minCoins(); }
return 0; }
This code is giving result 9 for 98(15*6+6*1+1*2) which is indeed correct right! but in problem the answer for 98 is 8.
15 * 5 + 10 * 2 + 3
You would never need more than 2 6s, 18=15+3 better than 6+6+6 and 24=15+3+6 better than 6+6+6+6
I was having the same doubt, that why they gave 4 sixes in the eidtorial
If you write C like this:
query a dot(x1,y1)
analyze which dot to query next (using many if-else)
and query (x2,y2)
and analyze all possible conditions...(using many if-else)
and query (x3,y3) ....
your code will easily become over 100 lines and have a very complex logic and also hard to write & debug. That's what I did in the contest.....qwq.
Maybe I should learn more. How to solve this kind of problem efficiently? Thanks for any ideas.
can someone please tell what was the rating of Problem B???
just wait for a few days, als why do you need the rating of a problem anyways?
just curious nothing else
For question B, there seems to be a better solution. 249111275 I like this solution by Sugar_fan, because it's linear time per test case after a tiny amount of precalculation. Could Sugar_fan himself or someone who gets it please explain a little bit on the solution? About why taking the remainder between m and 2m works and 0 and m does not?
As for the value of m in his/her solution (= 2700), I intuitively expanded on this idea and figured that in general m = lcm(numbers) will also work. As such here is an accepted solution (I simply changed m from 2700 to 30 in the code): 249254380, with 0ms, signifying O(1).
I also use this solution as I'm desperate. If anyone know how this solution works and prove it please tell me!!!
We need to prove this: for every $$$n>=30$$$ , the optimal choose must have a 15s coin.
prove: Consider an optimal choose that don't have 15s coin.
it have no more than 2*10s coin (3*10s coin->2*15s coin)
10s coin will not appear with 6s coin (10+6 = 15+1 , the optimal choose can have 15)
it have no more than 2*6s coin (3*6s coin -> 1*3s coin + 1*15s coin)
it have no more than 1*3s coin (2*3s coin -> 1*6s coin)
it have no more than 2*1s coin (3*1s coin -> 1*3s coin)
So , this optimal choose have sum of
2*1s + 1*3s + 2*10s = 25 < 30 (don't have 6s coin)
OR 2*1s + 1*3s + 2*6s = 17 < 30 (don't have 10s coin)
So exactly if n>25 we can greedy choose 15s coin.
In fact , 25=10+15 , 24=15+6+3 , 23 = 10+10+3 (if have 15s coin,it will be 15+6+1+1) , so the maximum n that we can't do greedy is 23.
Thanks, got what's going on. So you do greedy till your remaining number is <= 23, then you add the pre-calculation of the remainder. Or I can say, it can be shown that [can it?] the lcm is always >= (the number till which greedy can't be applied) [remains to be proven], and thus following what is done in the code, the remainder will always be , rem >= lcm >= lowest non greedy number, and thus works. Do you have anything to add?
An easier solution to D1. We just want to work on first 2 setbits of number n. I claim that if the first set bit of n is also set in b then the solution is always possible in 1 operation. Consider the example:
n = 5, m = 1. their binaries will be
Here, we can always have a value of s lesser than n such that its XOR with n will be also be lesser than n. For instance we can use
s = 100
and our value of n will be transformed into m. Case 2(m has a setbit between the first 2 setbits of n) Consider n = 5 and m = 3 The binaries will be ~~~~~ n = 101 m = 011 ~~~~~ Here we will always have to choose the second bit of s as 1 in order to reach m but it will be contra to the second condition of s < n. So the solution isn't possible in the test case. Case 3(We have first 2 setbits of n and m in same position): In this case we can always make n = m in just 2 operations. lets consider the example. n = 21, m = 5; The binaries will be:n = 10101; m = 00101
I know that this test case can be solved with case 1 but for the sake of explanation I'm using it. It's short and can help in understanding this case a lot.
First, we can choose s = 100001. How and why? If we set the first bit of s and leave the position of second set bit of n in s then we will have the independence to choose the leftover bits as we like as anyways, s is always going to be smaller than n. Thus, we have cut the problem into a position where we only check the positions between first 2 set bits of n. Once we are done with that, we can choose any s such that leftover bit gets toggled. Here, for instance, we could choose s = 00100 in the second step and hence, n will be transformed into m. Hope this helps someone. I have this code which does this job in time complexity closer to constant.
And thanks to Shayan for coming up with this approach.
I think I've got pretty interesting solution for B. It was knapsack problem, but with cunning trick.
Let's remove all 15 from number N. I mean like, lets cnt = n/15, then n -= cnt*15. Then just do DP with vector a = {1, 3, 6, 10}. And the answer will be cnt + dp[n] (because n is less than 15 it will pretty quick).
But there's a catch. Sometimes it is better to not take last 15 coin. For example, 98. With our method, answer will be 9 (15*6 + 6*1 + 1*2). But the correct answer is 8 (15*5 + 10*2 + 3*1).
So we should write two dps, one for n -= (n/15)*15, and the other is for (n/15-1)*15, and then output the minimal one min(dp1[n] + cnt1, dp2[N] + cnt2).
Cool problems! Thanks! I loved them.
For the problem C, I queried (1,1), (1,m),(n,1) and (n,m).
Let the manhattan distances be r1,r2,r3,r4.
So as in the solution I guessed 2 possible values of (x1,y1).Let them be (x11,y11){assuming r2 is distance from (x1,y1)} and x12,y12{assuming r3 is distance from (x2,y2) and r2 is distance from x1,y1}. Now using r4 ,we know for sure that r4=n-x2+m-y2 since we assumed x1+y1=r1.
We calculate the possible values of (x2,y2) using r4 and r3 (assuming (x1,y1) is calculated using r1 and r2 i.e (x1,y1)=(x11,y11)). Then to check out of (x11,y11) and (x12,y12) which one is the correct (x1,y1) we apply the condition that
I think my logic is correct ,but still my code is giving WA.What am i doing wrong here?
Here is my piece of code for reference.
perhaps your x11 y11 x21 y21 y12 x12 are floats...I don't understand why you're using float.The mines coordirates are all integers.
I'm using float so that i can identify when is r1+r2-m and similarly others are divisible by 2 or not. If you see carefully I have put a check in the if condition that
x11-(ll)x11!=0
which checks if x11 is integer or not. So if x11 or y11 is a decimal then the answer is (x12, y12)you don't need to check if the point is divisible by 2 or not. just query this point and you will know. and if you really want to get the answer in 3 queries just check if r1+r2-m is divisible by two and continue using integers. float won't fit anyways, try long double.
For a moment lets leave the discussion on floats or long doubles. I know i could query this point and if I get 0 ,then its the correct point otherwise the other is the correct point. But still I want to know what is wrong in my method or logic.It seems correct that I query (n,m) and then get a r4 to find the other point (x2,y2) and then apply the conditions for assuming that r2 is distance from (x1,y1) and r3 is distance from (x2,y2).
Bro sent the code as a spoiler or as a link
I'll take care the next time.
You can edit the comment
Very interesting problems, many thanks to the setters!. Just wanted to share my thoughts on problem A, as I thought it might help someone cuz it took a while for me to understand it well enough (or) intuitively.
The problem can be viewed as choosing any 4 elements from the initial array, and placing them along a circle in any order. Except that, we also want this ordering to give us the maximum possible sum of the absolute differences of the adjacent elements in the circle.
If we assume that we have chosen some 4 elements (we'll see how to choose them optimally a bit later), we just have to find a permutation along this circle that maximizes our goal.
Now, intuitively we can see that, placing the top 2 maximal elements (or equivalently the top 2 minimal elements) diametrically opposite to each other is the most optimal way, that gives 2*((max1+max2)-(min1+min2)) as the answer.
To prove this Intuitive claim of ours, let's consider elements a<=b<=c<=d. We can see that there are only 3 possible permutations with unique pairs of adjacents. This is because :
There are only (4-1)! = 6 circular permutations (Rotations are considered the same, cuz the adjacents are the same).
Among them as well, we must consider the mirror images (left-right inversion) to be the same (cuz the adjacents are the same). Therefore, we divide by 2, giving us 6/2 = 3 permutations.
To view these 3 permutations, consider the elements a,b,c,d to be permuted along the circle. Fix the position of a, now once we fix it's opposite element, the adjacents get fixed automatically.
Therefore, we only have 3 perms. ( a-b opposite, a-c opposite, a-d opposite ).
We can evaluate the answer for these 3 perms, as it has been done in the Editorial, and pick the maximum, which will turn out to be 2*((d+c)-(a+b)), thereby proving our intuitive claims. ( max1=d , max2=c , min1=a, min2=b )
Thus, for the overall problem, we can just pick the maximum two and the minimum two elements from the entire array, as this choice maximizes 2*((max1+max2)-(min1+min2)).
I'm sorry if this turned out to be lengthy. Also, feel free to correct me if there's something wrong in this.
Thanks for Reading :)
For the problem D2, if the number p has an even bit count, can I break it into p1=2^(lsb of p) and p2=p1⊕p , where lsb means the least significant bit?
In the Code Part of Solution to Problem D2, on Alice's turn, why does the code set curr into p1? Why cannot Bob choose p2 instead of p1?
.
For your first question:
For example take the number 1111000 in your turn. With your logic, you get 1110000 and 0001000 and you print it. Obviously the system will choose 1110000.
But here since only the XOR of two split numbers needs to be equal to 1110000; the system could print 1011111 and 0101111 (both are less than 1110000, constraints of the problem are met) so the lsb we removed can come back in cases like these. therefore, the interaction is not guaranteed to end in 63 operations.
but when we remove msb, it's impossible to get that same bit back again and we can finish the interaction in less than or equal to 63 operations.
Well, I forgot the constraint that up to 63 operations can be executed. I guess that is why I got TLE when I use lsb strategy. Thank you very much for pointing it out! :)
np :)
Измените код на С. 1 решение
Could somebody please explain why is this solution giving TLE for problem D2??
The given below is the link to my submission :- https://mirror.codeforces.com/contest/1934/submission/249353586
Use long long in your print function
Use lsb will exceed operations limitation. See this
For D2, can you explain while in third test for (n == 13) in a particular step shown in the sample bob didn't choose to break 10 -> 2 & 8 to win the game
Why my submission doesn't work (Problem C)? 249380440
My solution for B is a little interesting. https://mirror.codeforces.com/contest/1934/submission/249410271
n = 420
, its15 x 28
and10 x 42
, and42-28 = 14
14
less coins than other combinations, so even if the remainder is non-zero, it will be less than14
and we can use 1-value coin to fill the remainder, and it will still be optimal.10^9
to a number between420 and 435
by using only 15-value coins, then I rely on dp to tell me the minimal coins needed to consume the current number.Bro sent the code as a spoiler or as a link
B was similar to this spoj problem TPC07. Seems like others are picked from somewhere with minor conditions change only or is this a coincidence ?
For problem E, how does jury check whether the answer output by the contestant is correct? That is, how to write the Special Judge for this problem?
problem C sucks
another approach for B
Bro sent the code as a spoiler or as a link
Why exactly can't problem B be solve greedily. I came up with obvious cases: 20 = 10 + 10, 35 = 15 + 10, and so on. But why not?
for ex n=20: greedy chooses the greatest that's why the output is 4(15*1+3*1+1*2) but it must be 2(10*2)
This is My B number Code I think this is more easy than this code
include <bits/stdc++.h>
using namespace std; typedef long long int ll; int main() {
}
include<bits/stdc++.h>
using namespace std;
void rec(int in,vector &v,long long c,long long &ans,long long n) {
if(in>=v.size()) return;
} int main() { int t; cin>>t; while(t--) { long long n; cin >> n; long long ans =INT_MAX; vector v = {15, 10, 6, 3, 1}; int in = 0; for (in = 0; in < v.size(); in++) { if (v[in] <= n) break; } long long c=0; rec(in, v, c, ans, n);
why is this code not running for this test case 402931328
and giving the output
Exit code is -1073741571
Another solution for D1. Since we are allowed up to 63 operations, we can just do $$$\le1$$$ operation per bit. First let's assume there are at least 2 set bits in $$$n$$$.
For each bit $$$b$$$, if $$$b$$$ is the same in $$$m$$$ and $$$n$$$, then obviously we don't have to change it. Then we can break into two cases:
$$$1$$$: If $$$b$$$ is set in $$$n$$$ but not $$$m$$$, then we can add another operation flipping just that bit to $$$0$$$. Obviously, $$$b < n$$$ and $$$b\oplus n < n$$$, so this is valid.
$$$2$$$: If $$$b$$$ is set in $$$m$$$ but not $$$n$$$, then we can't have a separate operation, since then $$$b \oplus n > n$$$. Instead, let's combine this operation with an operation from case $$$1$$$, specifically the largest one. Note that since $$$m < n$$$, we will always encounter case $$$1$$$ before case $$$2$$$.
Now all we have to do is check if the largest operation is valid (because it may have been invalidated by case $$$2$$$ operations). There is an answer iff the largest operation is valid.
Problem: C
Can anyone tell me why my answer is giving the Idleness limit exceeded? What's wrong with my code?
my code: https://mirror.codeforces.com/contest/1934/submission/258188798
try remove line #define endl '\n'
more info — https://mirror.codeforces.com/blog/entry/63071
interactive problem for Problem C? That's not interesting.