Thanks to the $$$20$$$+ teams who participated in the TJIOI 2024 contest in-person and others who competed virtually in the mirror. We hope you enjoyed the problems! Please let us know in the comments if you have any questions or feedback.
[problem:523552A]
Idea: DanielQiu, Preparation: DanielQiu
#include <bits/stdc++.h>
using namespace std;
#define ll long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
ll x;
cin >> x;
if (x % 2 == 1) {
cout << "Cookie Monster" << endl;
} else {
int cnt = 0;
while(x % 2 == 0 && x) {
x /= 2;
cnt++;
}
if (cnt % 2 == 0) {
cout << "Cookie Monster" << endl;
} else {
cout << "Elmo" << endl;
}
}
}
[problem:523552B]
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, c; cin >> n >> m >> c;
c--;
c %= n + m;
if (c < n) cout << "Cookie Monster" << endl;
else cout << "Elmo" << endl;
}
[problem:523552C]
Idea: ChiMasterBing, Preparation: ChiMasterBing
#include <bits/stdc++.h>
using namespace std;
#define int long long
template<class T> struct SimpleSegmentTree {
int len;
vector<T> segtree;
T DEFAULT = {-1, -1};
SimpleSegmentTree(int _len) : len(_len), segtree(_len * 2, DEFAULT) {}
void set(int ind, T val) {
ind += len; segtree[ind] = val;
for (; ind > 1; ind /= 2) segtree[ind / 2] = merge(segtree[ind], segtree[ind ^ 1]);
}
T query(int start, int end) {
T res = DEFAULT;
for (start += len, end += len; start < end; start /= 2, end /= 2) {
if (start % 2 == 1) { res = merge(res, segtree[start++]); }
if (end % 2 == 1) { res = merge(res, segtree[--end]); }
}
return res;
}
T merge(T a, T b) {
if (a.first > b.first) return a;
else if (a.first == b.first) {
if (a.second < b.second) return a;
}
return b;
}
};
using SegTree = SimpleSegmentTree<pair<int, int>>; // (value, index)
struct block {
int L, R, H, LEN;
};
struct compare {
bool operator()(block const& a, block const& b) {
return a.LEN < b.LEN;
}
};
SegTree tree(0); //tree keeps track of highest nodes online. Used to get next "blocks" in O(log(N))
priority_queue<block, vector<block>, compare> pq; // (length, [L, R])
int N, Q;
void populate(block b) { //push adjacent blocks into PQ
int nxtL = b.L;
while (true) {
pair<int, int> p = tree.query(b.L, b.R + 1); //p is biggest, leftmost
if (p.first != b.H-1) break;
block nxt; nxt.L = nxtL; nxt.R = p.second-1; nxt.H = b.H-1; nxt.LEN = nxt.R-nxt.L+1;
nxtL = p.second + 1;
tree.set(p.second, {-1, -1});
if (nxt.LEN > 0) pq.push(nxt);
}
block nxt; nxt.L = nxtL; nxt.R = b.R; nxt.H = b.H-1; nxt.LEN = nxt.R-nxt.L+1;
if (nxt.LEN > 0) pq.push(nxt);
}
signed main() {
ios_base::sync_with_stdio(false); cin.tie(NULL);
cin>>N>>Q;
tree.segtree.resize(2 * N, {-1, -1});
tree.len = N;
for (int i=0; i<N; i++) {
int a; cin>>a; tree.set(i, {a, i});
}
int base = 0, T = tree.query(0, N).first;
block b; b.L = 0; b.R = N-1; b.LEN = b.R-b.L+1; b.H = T+1;
populate(b);
for (int i=0; i<T; i++) { //you can take T operations at most
if (pq.empty()) break;
block b = pq.top(); pq.pop();
base += b.LEN;
populate(b);
}
int zero = 0;
while (Q--) { //for more time, greedily take more blocks on top
int M; cin>>M;
M = max(zero, M-base);
int ans = T;
ans += (M / N);
M -= (M / N) * N;
if (M > 0) ans++;
cout<<ans<<"\n";
}
}
[problem:523552D]
Idea: avnithv, Preparation: avnithv
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
void solve() {
int n; cin >> n;
if (n % 4 == 2 || n % 4 == 3) {
cout << "No" << endl;
return;
}
cout << "Yes" << endl;
if (n == 1) {
cout << "1 2 3" << endl;
} else if (n == 4) {
cout << "1 5 6" << endl;
cout << "2 8 10" << endl;
cout << "3 9 12" << endl;
cout << "4 7 11" << endl;
} else if (n == 5) {
cout << "1 5 6" << endl;
cout << "2 10 12" << endl;
cout << "3 11 14" << endl;
cout << "4 9 13" << endl;
cout << "7 8 15" << endl;
} else if (n % 4 == 0) {
int l = 2*n, r = 3*n;
while (l != r) {
cout << r - l << " " << l << " " << r << endl;
l++; r--;
}
cout << n - 1 << " " << 3 * n / 2 + 1 << " " << 5 * n / 2 << endl;
cout << n / 2 - 1 << " " << 3 * n / 2 << " " << 2 * n - 1 << endl;
l = n + 1; r = 2 * n - 2;
while (r - l > n / 2 - 1) {
cout << r - l << " " << l << " " << r << endl;
l++; r--;
}
l = 3 * n / 2 - 1; r = 3 * n / 2 + 2;
while (r - l < n / 2 - 1) {
cout << r - l << " " << l << " " << r << endl;
l--; r++;
}
cout << 1 << " " << 5 * n / 4 << " " << 5 * n / 4 + 1 << endl;
} else {
int l = 2 * n + 1, r = 3 * n;
while (l != r) {
cout << r - l << " " << l << " " << r << endl;
l++; r--;
}
cout << n << " " << 3 * n / 2 + 1 << " " << 5 * n / 2 + 1 << endl;
cout << n / 2 - 1 << " " << 3 * n / 2 + 2 << " " << 2 * n << endl;
l = n + 1; r = 2 * n - 1;
while (r - l > n / 2 - 1) {
cout << r - l << " " << l << " " << r << endl;
l++; r--;
}
l = 3 * n / 2; r = 3 * n / 2 + 3;
while (r - l < n / 2 - 1) {
cout << r - l << " " << l << " " << r << endl;
l--; r++;
}
cout << 1 << " " << 5 * n / 4 + 1 << " " << 5 * n / 4 + 2 << endl;
}
}
int main() {
int t; cin >> t;
while (t--) solve();
}
[problem:523552E]
Idea: avnithv, Preparation: avnithv
#include <bits/stdc++.h>
using namespace std;
int main() {
int x, y, a, b; cin >> x >> y >> a >> b;
int ans = 2000000000;
if (a == x && b == y || a == y && b == x) ans = 0;
if (a <= x && b <= y) {
ans = min(ans, x + (a == x ? 0 : b));
ans = min(ans, y + (b == y ? 0 : a));
}
if (a <= y && b <= x) {
ans = min(ans, x + (b == x ? 0 : a));
ans = min(ans, y + (a == y ? 0 : b));
}
if (ans == 2000000000) ans = -1;
cout << ans << endl;
}
[problem:523552F]
Idea: avnithv, Preparation: avnithv
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
int n, m, q; cin >> n >> m >> q;
bool grid[n][m];
for (int i = 0; i < n; i++) {
string s; cin >> s;
for (int j = 0; j < m; j++) grid[i][j] = (s[j] == '1');
}
int pref[n+1][m+1];
memset(pref, 0, sizeof(pref));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
pref[i][j] += (int)grid[i-1][j-1] + pref[i-1][j] + pref[i][j-1] - pref[i-1][j-1];
}
}
// maximum width of subgrid with right column $$$i$$$ and height from rows $$$j$$$ to $$$k$$$.
int dp[m][n][n];
int pos[n][m];
memset(dp, 0, sizeof(dp));
memset(pos, 0, sizeof(pos));
for (int j = 0; j < n; j++) {
for (int k = j; k < n; k++) {
if (pref[k+1][1] - pref[k+1][0] - pref[j][1] + pref[j][0] == 0) {
dp[0][j][k] = 1;
pos[k-j][0]++;
}
}
}
for (int i = 1; i < m; i++) {
for (int j = 0; j < n; j++) {
for (int k = j; k < n; k++) {
if (pref[k+1][i+1] - pref[k+1][i] - pref[j][i+1] + pref[j][i] == 0) {
dp[i][j][k] = dp[i-1][j][k]+1;
pos[k-j][dp[i][j][k]-1]++;
} else dp[i][j][k] = 0;
}
}
}
for (int i = 0; i < n; i++) {
for (int j = m-2; j >= 0; j--) {
pos[i][j] += pos[i][j+1];
}
}
while (q--) {
int h, w; cin >> h >> w;
h--; w--;
cout << pos[h][w] << endl;
}
}
[problem:523552G]
#include <bits/stdc++.h>
using namespace std;
int main() {
int x, y, z;
cin >> x >> y >> z;
cout << min(x, y) << endl;
}
[problem:523552H]
Idea: DanielQiu, Preparation: DanielQiu
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
string a, b;
cin>>a>>b;
int cnta[26];
int cntb[26];
memset(cnta, 0, sizeof(cnta));
memset(cntb, 0, sizeof(cntb));
for(char c: a){
cnta[c-'a']++;
}
for(char c: b){
cntb[c-'a']++;
}
int ret = INT_MAX;
for(int i=0; i<26; i++){
if(cntb[i]>0){
ret = min(ret, cnta[i]/cntb[i]);
}
}
cout<<ret<<endl;
}
[problem:523552I]
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, d, m; cin >> n >> d >> m;
vector<int> arr(n);
for (int i = 0; i < n; i++) cin >> arr[i];
map<int, vector<int>> mp;
for (int i = 0; i < n; i++) {
int rem = arr[i] % d;
int b = (arr[i]-rem)/d;
if (!mp.count(rem)) mp[rem] = vector<int>();
mp[rem].push_back(b);
}
int ans = 0;
for (auto x : mp) {
vector<int> v = x.second;
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
int l = v.size();
for (int i = l-1; i >= 0; i--) {
if (l - i == m) {
l--;
ans++;
}
if (i > 0 && v[i-1]+1 < v[i]) l=i;
}
}
cout << ans << endl;
}
[problem:523552J]
#include <bits/stdc++.h>
using namespace std;
const int mn=2e5;
vector<int> adj[mn];
bool visited[mn]={0};
int cost[mn];
int dfs(int node) {
visited[node]=true;
long long subtree_sum=0;
for(int u:adj[node]) {
if(!visited[u]) {
subtree_sum+=dfs(u);
}
}
if(subtree_sum==0) return cost[node];
return min((long long)cost[node], subtree_sum);
}
int main() {
int n, h; cin >> n >> h;
for(int i=0; i<n; i++) cin >> cost[i];
for(int i=0; i<n-1; i++) {
int u, v; cin >> u >> v;
u--, v--;
adj[u].push_back(v);
adj[v].push_back(u);
}
cout << (long long)dfs(0)*h;
}
[problem:523552K]
Idea: avnithv, Preparation: avnithv
#include <bits/stdc++.h>
using namespace std;
int main() {
int t; cin >> t;
while (t--) {
int n; cin >> n;
vector<int> arr(n);
for (int i = 0; i < n; i++) cin >> arr[i];
int ans=1;
for (int i = 0; i < n-1; i++) {
if (arr[i] < arr[i+1]) ans++;
}
cout << ans << endl;
}
}
[problem:523552L]
Idea: MunirKP, Preparation: MunirKP
from functools import cmp_to_key
def cross(p, q, r):
v = (r[0]-p[0], r[1]-p[1])
w = (q[0]-p[0], q[1]-p[1])
return (v[1]*w[0] - v[0]*w[1])
def convex_hull(pnts):
lv, li = min((v,i) for i,v in enumerate(pnts))
cnds = sorted({*pnts}-{lv}, key=cmp_to_key(lambda a, b : cross(lv, a, b)))
hull = [lv]
for pt in cnds:
while len(hull) > 1 and cross(hull[-2], hull[-1], pt) >= 0:
hull.pop()
hull.append(pt)
return hull
def main():
N = int(input())
pnts = [tuple(map(int, input().split())) for i in range(N)]
oh = convex_hull(pnts)
if len(oh) == len(pnts):
print(len(oh))
if pnts[1]==oh[-1]:
print('\n'.join(f"{p[0]} {p[1]}" for p in [oh[-1],oh[1],oh[0]]+oh[2:-1]))
else:
print('\n'.join(f"{p[0]} {p[1]}" for p in [oh[1],oh[0]]+oh[2:]))
return
ih = convex_hull([*{*pnts} - {*oh}])
pivs = [pnts[1]]
ii = 0
st = 0
if pnts[1]==oh[1] and oh[1][1] > oh[0][1]:
pivs.append(oh[0])
st = 1
for oi in [*range(st,len(oh))]+[0]:
if len(ih)==2:
if cross(oh[oi], ih[ii], ih[(ii+1)%len(ih)]) > 0: ii = (ii+1)%len(ih)
elif len(ih)>2:
while cross(oh[oi], ih[ii], ih[(ii+1)%len(ih)]) > 0: ii = (ii+1)%len(ih)
while cross(pivs[-1], ih[ii], oh[(oi+1)%len(oh)]) < 0:
pivs.append(ih[ii])
ii = (ii+1)%len(ih)
pivs.append(oh[(oi+1)%len(oh)])
pivs.append(oh[oi])
oi = (oi+1)%len(oh)
vis = {pt:len(pivs)-i-1 for i,pt in enumerate(pivs[::-1])}
print(len(vis))
print('\n'.join(f"{pt[0]} {pt[1]}" for i,pt in enumerate(pivs) if vis[pt]==i))
if __name__=='__main__': main()
[problem:523552M]
Idea: flight, Preparation: flight
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
const int MOD = 1e9+7;
template<const int MOD> struct Modular {
static const int mod = MOD;
int v; explicit operator int() const { return v; }
Modular():v(0) {}
Modular(ll _v) { v = int((-MOD < _v && _v < MOD) ? _v : _v % MOD); if (v < 0) v += MOD; }
friend Modular mpw(Modular a, ll p) {
Modular ans = 1;
for (; p; p /= 2, a *= a) if (p&1) ans *= a;
return ans; }
friend Modular inv(const Modular& a) { return mpw(a,MOD-2);}
friend bool operator!=(const Modular& a, const Modular& b) { return !(a == b); }
friend bool operator<(const Modular& a, const Modular& b) { return a.v < b.v; }
Modular& operator+=(const Modular& o) { if ((v += o.v) >= MOD) v -= MOD; return *this; }
Modular& operator-=(const Modular& o) { if ((v -= o.v) < 0) v += MOD; return *this; }
Modular& operator*=(const Modular& o) { v = int((ll)v*o.v%MOD); return *this; }
Modular& operator/=(const Modular& o) { return (*this) *= inv(o); }
Modular operator-() const { return Modular(-v); }
Modular& operator++() { return *this += 1; }
Modular& operator--() { return *this -= 1; }
friend Modular operator+(Modular a, const Modular& b) { return a += b; }
friend Modular operator-(Modular a, const Modular& b) { return a -= b; }
friend Modular operator*(Modular a, const Modular& b) { return a *= b; }
friend Modular operator/(Modular a, const Modular& b) { return a /= b; }
friend istream& operator>>(istream& inp, Modular& a) { ll x; inp >> x; a = Modular(x); return inp;}
friend ostream& operator<<(ostream& out, const Modular& a) { out << a.v; return out; }
};
using Mint = Modular<MOD>;
using Mint = Modular<MOD>;
const int mxN = 1e6 + 10;
vector<Mint> f(mxN), invf(mxN);
Mint modpow(Mint x, int e) {
Mint base = x, curr = 1;
while (e) {
if (e & 1) {
curr *= base;
}
base = base * base;
e >>= 1;
}
return curr;
}
void precompute_factorials() {
f[0] = 1;
for (int i = 1; i < mxN; i++) {
f[i] = f[i-1] * i;
}
invf[mxN - 1] = modpow(f.back(), MOD - 2);
for (int i = mxN - 2; i >= 0; i--) {
invf[i] = invf[i+1] * (i + 1);
}
}
Mint nCr(int n, int r) {
return f[n] * invf[n-r] * invf[r];
}
int32_t main(){
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
precompute_factorials();
int n, k; cin >> n >> k;
if (n % k != 0) {
cout << 0 << "\n";
return 0;
}
int r = n / k;
Mint prod = (f[n] * invf[r]) / modpow(k, r);
for (int i = 1; i < r; i++){
prod *= (i * k + 1);
}
cout << prod << "\n";
}