π§© AtCoder Beginner Contest 367
π§© AtCoder Beginner Contest 367
# Info & Summary
- Date:
2024-08-17
- Completion Status: A β / B β / C β / D β / E β / F β / G β
- Problem Type:
Problem | Type(s) | Data Structure / Algo | π₯ Key Insight / Mark |
---|---|---|---|
D | Prefix Sum | Prefix Sum | βπ₯ |
E | Function Exponentiation | Binary Lifting/Doubling | π§ π οΈπ |
F | determine if two sets are equal | Zobrist Hash | π |
G | Math | XOR convolution & Hadamard transform | π |
Details
Emoji | Label | Meaning |
---|---|---|
β | Important | Problem is strategically useful or has reusable patterns |
π₯ | Must master | Classic problem or technique that appears often and is worth mastering |
β οΈ | Reattempt | You attempted but failed; worth reviewing and solving again |
π§ | New to me | Introduced a new idea, technique, or pattern you hadnβt seen before |
π οΈ | Template | You built or improved a code template from solving this problem |
π | Too hard now | Beyond current ability to understand/solve; revisit after more practice |
π A - Shout Everyday

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int A, B, C;
cin >> A >> B >> C;
if (B < C)
{
if (B < A && A < C)
{
cout << "No" << endl;
}
else
{
cout << "Yes" << endl;
}
}
else
{
if (C < A && A < B)
{
cout << "Yes" << endl;
}
else
{
cout << "No" << endl;
}
}
return 0;
}
π B - Cut .0

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
string S;
cin >> S;
while (S.back() == '0')
{
S.pop_back();
}
if (S.back() == '.')
{
S.pop_back();
}
cout << S << endl;
return 0;
}
π C - Enumerate Sequences

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, K;
cin >> N >> K;
vector<int> R(N);
for (int i = 0; i < N; i++)
{
cin >> R[i];
}
vector<vector<int>> ans;
vector<int> v;
auto dfs = [&](auto &&self, int p, int sum) -> void
{
if (p == N)
{
if (sum % K == 0)
{
ans.push_back(v);
}
return ;
}
for (int r = 1; r <= R[p]; r++)
{
v.push_back(r);
self(self, p + 1, sum + r);
v.pop_back();
}
};
dfs(dfs, 0, 0);
for (auto v : ans)
{
for (int i = 0; i < N; i++)
{
cout << v[i] << " \n"[i == N - 1];
}
}
return 0;
}
π D - Pedometer

Tips
Let:
We want:
Tips
Define pre[i]
:
pre[i]
: the total steps from rest area up to (but not including) rest area
then we got:
- if , then the distance:
- if , then the distance:
where
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, M;
cin >> N >> M;
vector<long long> A(N);
for (int i = 0; i < N; i++)
{
cin >> A[i];
}
map<int, int> cnt;
long long ans = 0;
vector<long long> pre(N + 1);
for (int i = 0; i < N; i++)
{
pre[i + 1] = pre[i] + A[i];
}
const long long L = pre[N];
for (int i = 0, j = 0; i < N; i++)
{
ans += cnt[(pre[i] - L % M + M) % M];
ans += cnt[pre[i] % M];
cnt[pre[i] % M]++;
}
cout << ans << endl;
return 0;
}
π E - Permute K times

Function Exponentiation
We have:
- A function on the set , given by an array where
- An initial array of length
- A nonnegative integer , potentially as large as
We want to compute, for each position , the element:
where is applied times
A native simulation takes , which is impossible for large
Binary-Lifting to Compute in
Instead, we use binary lifting
(sometimes called doubling
or function exponentiation
) to do it in
Key idea: Decompose K in powers of two
Any integer can be written in binary:
Then
So if we can precompute each -fold iterate , we can build by selecting only those powers of two that appear in the binary expansion of
Precompute Doubling
Table Implicitly
Instead of an explicit 2D table , we keeps a single array that it repeatedly square
in place:
- Initially,
- After one
square
step, - Ans after
square
s,
Concurrently, we maintain an accumulator array Y[i]
that starts as the identity . Whenever the current lowest bit of is 1
, we apply the present (which equals ) to Y
After we processed all bits in this way,
Once we know for each index the value , the element at position in the -th iterate of is simply
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
long long K;
cin >> N >> K;
vector<int> X(N);
for (int i = 0; i < N; i++)
{
cin >> X[i];
X[i]--;
}
// Initialize the βaccumulatorβ array Y
// We'll maintain Y[i] = f^{(\text{processed bits of }K)}(i)
// Initially, Y[i] = i (zero applications)
vector<int> Y(N);
iota(Y.begin(), Y.end(), 0);
// Binary-exponentiate
while (K > 0)
{
// If the current lowest bit of K is 1, apply the current power of X to Y
if (K % 2 == 1)
{
for (int i = 0; i < N; i++)
{
Y[i] = X[Y[i]];
}
}
// Square the mapping X β X β X (so X[i] now equals f(f(i)) for next bit)
vector<int> tmp(N);
for (int i = 0; i < N; i++)
{
tmp[i] = X[X[i]];
}
X = move(tmp);
// shift out the bit we just handled
K /= 2;
}
vector<int> A(N);
for (int i = 0; i < N; i++)
{
cin >> A[i];
}
// Finally, after K applications, position i in the resulting array
// was originally at A[Y[i]]
for (int i = 0; i < N; i++)
{
cout << A[Y[i]] << " \n"[i == N - 1];
}
return 0;
}
π F - Rearrange Query

Warning
Hard Problems to Tackle Later
// TODO
π G - Sum of (XOR^K or 0)

Warning
Hard Problems to Tackle Later
// TODO