Имя входного файла: стандартный ввод Имя выходного...
Créé le : 31 mars 2026
Répondu en utilisant GPT-5.4 Thinking par Chat01
Créé le : 31 mars 2026
Répondu en utilisant GPT-5.4 Thinking par Chat01
Имя входного файла: стандартный ввод
Имя выходного файла: стандартный вывод
Ограничение по времени: 2 секунды
Ограничение по памяти: 512 мегабайт
Марсианские профессора — настоящие мастодонты своего дела. Они завоевали не один десяток
наград во всевозможных сферах — от антропологии, биологии и социологии до физики и информатики. И сегодня марсианские ученые представляют научному комитету свою новую монументальную работу в области математики. Они изобрели концептуально новый вид последовательностей —
марсианский ряд !
Марсианский ряд обозначается буквой M. Первое число марсианского ряда равно M0 = 0. Число
Mi определяется как минимальное целое неотрицательное число, которое не встречается в марсианском ряду на отрезке от
i
2
до i − 1 включительно. Более формально,
Mi = MEX
Mj по всем
i
2
⩽ j ⩽ i − 1
,
где MEX — минимальное целое неотрицательное число, не представленное в данном множестве.
Комиссия с интересом выслушала доклад марсианских профессоров, после которого у неё появилось целых q вопросов. По забавному совпадению, все вопросы имели одинаковый формат:
«Подскажите, а если мы для некоторых l и r возьмём числа Ml
, Ml+1, . . . , Mr и отсортируем их
в порядке неубывания, какое число будет находиться на k-й позиции слева?»
Вопросы весьма интересны, однако из-за короткого периода концентрации внимания в будущем
марсианским профессорам отводится всего одна минута на весь доклад и ответы на вопросы, и они
боятся не успеть произвести все вычисления вовремя. Сможете ли вы им помочь?
Формат входных данных
В первой строке находится одно целое число q (1 ⩽ q ⩽ 105
) — количество вопросов от комиссии.
Далее следуют параметры вопросов.
В каждой из следующих q строк находятся три целых числа l, r и k (0 ⩽ l ⩽ r ⩽ 109
,
1 ⩽ k ⩽ r − l + 1) — параметры вопроса комиссии.
Формат выходных данных
Для каждого вопроса выведите одно целое число в отдельной строке — ответ на очередной вопрос
комиссии.
Страница 3 из 9
Заключительный этап республиканской олимпиады по учебному предмету «Информатика»
2 тур. Вариант 1., 2025/2026 учебный год
Система оценки
№ Дополнительные ограничения Баллы за подзадачу Необходимые подзадачи
1 q, l, r ⩽ 200 5
2 q, l, r ⩽ 2000 13 1
3 l, r ⩽ 2 · 105 17 1-2
4 Сумма по всем r − l + 1 ⩽ 106 20 1
5 k = r − l + 1 5
6 k = 1 17
7 k ⩽ 5 11 6
8 Нет дополнительных ограничений 12 1-7
Пример
стандартный ввод стандартный вывод
4
0 1 1
1 4 2
0 5 6
0 4 4
0
1
3
1
Замечание
Первые шесть значений марсианского ряда принимают следующие значения:
M0 = 0
M1 = MEX (M0) = MEX (0) = 1
M2 = MEX (M1) = MEX (1) = 0
M3 = MEX (M1, M2) = MEX (1, 0) = 2
M4 = MEX (M2, M3) = MEX (0, 2) = 1
M5 = MEX (M2, M3, M4) = MEX (0, 2, 1) = 3
Для второго вопроса из тестового примера последовательность элементов равна 1, 0, 2, 1. Если
отсортировать в порядке неубывания, то получим 0, 1, 1, 2. Число на второй позиции равно 1 — ответ
на соответствующий вопрос.
Для третьего вопроса из тестового примера последовательность элементов равна 0, 1, 0, 2, 1, 3.
Если отсортировать в порядке неубывания, то получим 0, 0, 1, 1, 2, 3. Число на шестой позиции равно
3 — ответ на соответствующий вопрос.
#include <bits/stdc++.h>
#define int long long
using namespace std;
using ll = long long;
const int N = 1e9 + 7;
const int C = 380;
const int B = 128;
void solve() {
int l, r, j;
cin >> l >> r >> j;
vector< int > x1(32 + 1), x2(32 + 1), x3(32 + 1);
x1[0] = 0;
x2[0] = 1;
x3[0] = 2;
for (int i = 1; i <= 32; i++) {
x2[i] = x2[i - 1] * 2;
x3[i] = x3[i - 1] * 2;
x1[i] = x3[i] - 2;
if (x1[i] > r) {
break;
}
}
auto ok = [&](int x) {
int ans = 0;
for (int i = 0; i <= 32; i++) {
if (x1[i] > r) {
break;
}
if (x1[i] >= l) ans++;
int rr = r - (x2[i] + x1[i] - 1);
int ll = l - (x2[i] + x1[i] - 1);
if (rr < 0) rr = 0;
if (ll < 0) ll = 0;
ans += min(rr / x3[i] + 1, x);
ans -= (ll / x3[i]);
// cout<< x << ":" << i << ":" << ans << "\n";
}
return ans;
};
int l1 = -1, r1 = r;
while (r1 - l1 > 1) {
int mid = (l1 + r1) / 2;
if (ok(mid) >= j) r1 = mid;
else l1 = mid;
}
cout<< r1 << "\n";
}
int32_t main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
srand(time(0));
int tests = 1;
cin>>tests;
while (tests--) {
solve();
}
return 0;
}
/*
0-1-2
2-2-4
6-4-8
14-8-16
30-16-32
62-32-64
////////////////////
0 1 3 5 7 9
2 4 8
6 10
1
0 5 6
2:3
x x x x 2 x
0 1 0 2 1 3
*/
логига +- норм 1 тест проходит но не все тесты проходят найди ошибкку и покажи как и где исправить минимально меняя код
pythondef mars(n): M=[0] for i in range(1,n+1): s=set(M[(i+1)//2:i]) # ceil(i/2)= (i+1)//2 x=0 while x in s: x+=1 M.append(x) return M M=mars(100) M[:40] [0, 0, 1, 0, 2, 1, 3, 0, 4, 2, 5, 1, 6, 3, 7, 0, 8, 4, 9, 2, 10, 5, 11, 1, 12, 6, 13, 3, 14, 7, 15, 0, 16, 8, 17, 4, 18, 9, 19, 2]
pythondef mars(n): M=[0] for i in range(1,n+1): s=set(M[i//2:i]) # floor(i/2) x=0 while x in s: x+=1 M.append(x) return M M=mars(100) M[:40] [0, 1, 0, 2, 1, 3, 0, 4, 2, 5, 1, 6, 3, 7, 0, 8, 4, 9, 2, 10, 5, 11, 1, 12, 6, 13, 3, 14, 7, 15, 0, 16, 8, 17, 4, 18, 9, 19, 2, 20]
pythonfrom collections import defaultdict M=mars(200) pos=defaultdict(list) for i,v in enumerate(M): pos[v].append(i) for v in range(10): print(v, pos[v][:20], 'len',len(pos[v]))
pythondef code_ok(l,r,x): x1=[0]*33;x2=[0]*33;x3=[0]*33 x1[0]=0;x2[0]=1;x3[0]=2 for i in range(1,33): x2[i]=x2[i-1]*2 x3[i]=x3[i-1]*2 x1[i]=x3[i]-2 if x1[i]>r: break ans=0 for i in range(33): if x1[i]>r: break if x1[i]>=l: ans+=1 rr=r-(x2[i]+x1[i]-1) ll=l-(x2[i]+x1[i]-1) if rr<0: rr=0 if ll<0: ll=0 ans+=min(rr//x3[i]+1, x) ans-= (ll//x3[i]) return ans def brute_count(l,r,x): M=mars(r) return sum(v<=x for v in M[l:r+1]) for l in range(0,10): for r in range(l,20): for x in range(0,6): a=code_ok(l,r,x) b=brute_count(l,r,x) if a!=b: print("mismatch",l,r,x,a,b) raise SystemExit print("all ok small")
pythondef mars(n): M=[0] for i in range(1,n+1): s=set(M[i//2:i]) x=0 while x in s: x+=1 M.append(x) return M def code_ok(l,r,x): x1=[0]*33;x2=[0]*33;x3=[0]*33 x1[0]=0;x2[0]=1;x3[0]=2 for i in range(1,33): x2[i]=x2[i-1]*2 x3[i]=x3[i-1]*2 x1[i]=x3[i]-2 if x1[i]>r: break ans=0 for i in range(33): if x1[i]>r: break if x1[i]>=l: ans+=1 rr=r-(x2[i]+x1[i]-1) ll=l-(x2[i]+x1[i]-1) if rr<0: rr=0 if ll<0: ll=0 ans+=min(rr//x3[i]+1, x) ans-= (ll//x3[i]) return ans M = mars(50) for x in range(5): print("x=",x," code=",code_ok(0,0,x)," brute=",sum(v<=x for v in M[0:1])) print("M[0..10]=",M[:11])
pythondef code_answer(l,r,j): lo=-1; hi=r while hi-lo>1: mid=(lo+hi)//2 if code_ok(l,r,mid)>=j: hi=mid else: lo=mid return hi queries=[(0,1,1),(1,4,2),(0,5,6),(0,4,4)] for q in queries: l,r,j=q M=mars(r) arr=sorted(M[l:r+1]) print(q, code_answer(*q), arr[j-1], arr)
pythondef brute_answer(l,r,k): M=mars(r) arr=sorted(M[l:r+1]) return arr[k-1] bad=[] for l in range(0,20): for r in range(l,40): for k in range(1,r-l+2): a=code_answer(l,r,k) b=brute_answer(l,r,k) if a!=b: bad.append((l,r,k,a,b,sorted(mars(r)[l:r+1]))) if len(bad)>=20: break if len(bad)>=20: break if len(bad)>=20: break len(bad), bad[:10] (20, [(0, 3, 4, 1, 2, [0, 0, 1, 2]), (0, 6, 6, 1, 2, [0, 0, 0, 1, 1, 2, 3]), (0, 6, 7, 2, 3, [0, 0, 0, 1, 1, 2, 3]), (0, 7, 6, 1, 2, [0, 0, 0, 1, 1, 2, 3, 4]), (0, 7, 7, 2, 3, [0, 0, 0, 1, 1, 2, 3, 4]), (0, 7, 8, 2, 4, [0, 0, 0, 1, 1, 2, 3, 4]), (0, 8, 6, 1, 2, [0, 0, 0, 1, 1, 2, 2, 3, 4]), (0, 8, 8, 2, 3, [0, 0, 0, 1, 1, 2, 2, 3, 4]), (0, 8, 9, 3, 4, [0, 0, 0, 1, 1, 2, 2, 3, 4]), (0, 9, 6, 1, 2, [0, 0, 0, 1, 1, 2, 2, 3, 4, 5])])
pythonl,r=0,3 for x in range(5): print(x, code_ok(l,r,x), brute_count:=sum(v<=x for v in mars(r)[l:r+1]))
pythondef contribs(l,r,x): x1=[0]*33;x2=[0]*33;x3=[0]*33 x1[0]=0;x2[0]=1;x3[0]=2 for i in range(1,33): x2[i]=x2[i-1]*2 x3[i]=x3[i-1]*2 x1[i]=x3[i]-2 if x1[i]>r: break ans=0 arr=[] for i in range(33): if x1[i]>r: break cur=0 if x1[i]>=l: cur+=1 rr=r-(x2[i]+x1[i]-1) ll=l-(x2[i]+x1[i]-1) if rr<0: rr=0 if ll<0: ll=0 cur+=min(rr//x3[i]+1, x) cur-= (ll//x3[i]) arr.append((i,cur,x1[i],x2[i]+x1[i]-1,x3[i])) ans+=cur return ans,arr for x in [0,1,2]: a,arr=contribs(0,3,x) print('x',x,'ans',a,arr)
pythondef count_correct(l,r,x): ans=0 pw=1 while pw<=r+2: a=(l+2 + pw -1)//pw b=(r+2)//pw lo=max(a,1) hi=min(b,2*x+1) if lo<=hi: ans += (hi+1)//2 - (lo//2) pw*=2 return ans for l in range(0,20): for r in range(l,40): M=mars(r) for x in range(0,10): b=sum(v<=x for v in M[l:r+1]) c=count_correct(l,r,x) if b!=c: print("mismatch",l,r,x,b,c) raise SystemExit print("all good")
Да, ошибка у тебя именно в ok(x).
Твоя идея с бинарным поиском по ответу нормальная, но функция ok(x) неправильно считает количество элементов <= x на отрезке.
Из-за этого бинарный поиск иногда уезжает в меньший ответ.
Например, возьмём отрезок [0, 3].
Марсианский ряд там такой:
cppM = [0, 1, 0, 2]
Отсортировано:
cpp[0, 0, 1, 2]
Значит:
<= 0 — 2<= 1 — 3А твоя функция считает:
ok(0) = 2 — нормальноok(1) = 4 — ошибкаТо есть она уже для x = 1 думает, что на отрезке все 4 элемента не больше 1, хотя это не так (2 > 1).
Вот эта строка неверная:
cppans += min(rr / x3[i] + 1, x);
Она предполагает, что на каждом “слое” количество подходящих значений ограничивается просто числом x,
но у марсианского ряда распределение значений устроено иначе.
Для марсианского ряда верна формула:
cppMi = (odd(i + 2) - 1) / 2
где odd(n) — нечётная часть числа n
(то есть делим n на 2, пока оно чётное).
Примеры:
i = 0: i + 2 = 2, нечётная часть 1, получаем 0i = 3: i + 2 = 5, нечётная часть 5, получаем 2i = 5: i + 2 = 7, нечётная часть 7, получаем 3Значит условие
cppMi <= x
равносильно
cppodd(i + 2) <= 2 * x + 1
Это уже можно корректно посчитать за O(log r).
Нужно заменить только ok.
Остальной код, включая бинарный поиск, можно оставить как есть.
cppauto ok = [&](int x) { int ans = 0; for (int i = 0; i <= 32; i++) { if (x1[i] > r) { break; } if (x1[i] >= l) ans++; int rr = r - (x2[i] + x1[i] - 1); int ll = l - (x2[i] + x1[i] - 1); if (rr < 0) rr = 0; if (ll < 0) ll = 0; ans += min(rr / x3[i] + 1, x); ans -= (ll / x3[i]); // cout<< x << ":" << i << ":" << ans << "\n"; } return ans; };
cppauto ok = [&](int x) { int ans = 0; int lim = 2 * x + 1; // odd(i+2) <= lim for (int pw = 1; pw <= r + 2; pw <<= 1) { // ищем числа i, для которых i+2 = pw * t, где t нечётное int L = (l + 2 + pw - 1) / pw; // ceil((l+2)/pw) int R = (r + 2) / pw; // floor((r+2)/pw) L = max(L, 1LL); R = min(R, lim); if (L <= R) { // количество нечётных чисел на [L, R] ans += (R + 1) / 2 - L / 2; } } return ans; };
cpp#include <bits/stdc++.h> #define int long long using namespace std; using ll = long long; const int N = 1e9 + 7; const int C = 380; const int B = 128; void solve() { int l, r, j; cin >> l >> r >> j; auto ok = [&](int x) { int ans = 0; int lim = 2 * x + 1; for (int pw = 1; pw <= r + 2; pw <<= 1) { int L = (l + 2 + pw - 1) / pw; int R = (r + 2) / pw; L = max(L, 1LL); R = min(R, lim); if (L <= R) { ans += (R + 1) / 2 - L / 2; } } return ans; }; int l1 = -1, r1 = r; while (r1 - l1 > 1) { int mid = (l1 + r1) / 2; if (ok(mid) >= j) r1 = mid; else l1 = mid; } cout << r1 << "\n"; } int32_t main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int tests = 1; cin >> tests; while (tests--) { solve(); } return 0; }
Только это:
okДля входа:
cpp4 0 1 1 1 4 2 0 5 6 0 4 4
получится:
cpp0 1 3 1
что совпадает с примером.
Если хочешь, я могу ещё очень коротко расписать, почему формула Mi = (odd(i+2)-1)/2 верна, чтобы ты мог защитить это решение на разборе.