Here is the tutorial of Hello 2018. Enjoy!
Modular Exponentiation
Problem writer: tourist
Tutorial is loading...
Solution
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
scanf("%d %d", &n, &m);
printf("%d\n", n >= 31 ? m : m % (1 << n));
return 0;
}
Christmas Spruce
Problem writer: budalnik
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> p(n), deg(n);
for (int i = 1; i < n; i++) {
cin >> p[i];
p[i]--;
deg[p[i]]++;
}
vector<int> sons_leaves(n);
for (int i = 0; i < n; i++) {
if (deg[i] == 0) {
sons_leaves[p[i]]++;
}
}
for (int i = 0; i < n; i++) {
if (deg[i] > 0 && sons_leaves[i] < 3) {
puts("No");
return 0;
}
}
puts("Yes");
return 0;
}
Python solution
n = int(input())
p = [int(input()) - 1 for _ in range(n - 1)]
leafs = list(filter(lambda x: not x in p, range(n)))
lp = [x for i, x in enumerate(p) if i + 1 in leafs]
x = min(lp.count(k) for k in p)
print("Yes" if x >= 3 else "No")
Party Lemonade
Problem writer: tourist [tutorial:913С]
Solution
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, L;
scanf("%d %d", &n, &L);
vector<int> c(n);
for (int i = 0; i < n; i++) {
scanf("%d", &c[i]);
}
for (int i = 0; i < n - 1; i++) {
c[i + 1] = min(c[i + 1], 2 * c[i]);
}
long long ans = (long long) 4e18;
long long sum = 0;
for (int i = n - 1; i >= 0; i--) {
int need = L / (1 << i);
sum += (long long) need * c[i];
L -= need << i;
ans = min(ans, sum + (L > 0) * c[i]);
}
cout << ans << endl;
return 0;
}
Too Easy Problems
Problem writer: tourist
Tutorial is loading...
Solution with binary search
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, T;
scanf("%d %d", &n, &T);
vector<int> a(n), t(n);
for (int i = 0; i < n; i++) {
scanf("%d %d", &a[i], &t[i]);
}
vector<int> res;
int low = 0, high = n;
while (low < high) {
int mid = (low + high + 1) >> 1;
vector< pair<int,int> > e;
for (int i = 0; i < n; i++) {
if (a[i] >= mid) {
e.emplace_back(t[i], i);
}
}
sort(e.begin(), e.end());
bool ok = false;
if ((int) e.size() >= mid) {
int sum = 0;
for (int i = 0; i < mid; i++) {
sum += e[i].first;
}
if (sum <= T) {
ok = true;
res.resize(mid);
for (int i = 0; i < mid; i++) {
res[i] = e[i].second;
}
}
}
if (ok) {
low = mid;
} else {
high = mid - 1;
}
}
int sz = (int) res.size();
printf("%d\n%d\n", sz, sz);
for (int i = 0; i < sz; i++) {
if (i > 0) {
putchar(' ');
}
printf("%d", res[i] + 1);
}
printf("\n");
return 0;
}
Solution with set
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, T;
scanf("%d %d", &n, &T);
vector< vector< pair<int, int> > > at(n + 1);
for (int i = 0; i < n; i++) {
int foo, bar;
scanf("%d %d", &foo, &bar);
at[foo].emplace_back(bar, i);
}
vector<int> res;
set< pair<int, int> > s;
int sum = 0;
for (int k = n; k > 0; k--) {
for (auto &p : at[k]) {
sum += p.first;
s.emplace(p);
}
while ((int) s.size() > k) {
sum -= (--s.end())->first;
s.erase(--s.end());
}
if ((int) s.size() == k && sum <= T) {
for (auto &p : s) {
res.push_back(p.second);
}
break;
}
}
int sz = (int) res.size();
printf("%d\n%d\n", sz, sz);
for (int i = 0; i < sz; i++) {
if (i > 0) {
putchar(' ');
}
printf("%d", res[i] + 1);
}
printf("\n");
return 0;
}
Logical Expression
Problem writer: budalnik
Tutorial is loading...
Solution 1
#include <iostream>
#include <set>
#include <vector>
#include <string>
using namespace std;
bool ls(const string& a, const string& b) {
if (a.length() == b.length()) return a < b;
return a.length() < b.length();
}
struct Expression {
int p, t;
string e;
Expression(string _e, int t_, int _p) : e(_e), t(t_), p(_p) {}
bool operator < (const Expression& ex) const {
if (ex.e == e) {
if (t != ex.t) {
return t < ex.t;
}
return p < ex.p;
}
return ls(e, ex.e);
}
};
set<Expression> q;
const int FULL = 0xff;
const vector<int> B = {1, 2, 4, 8, 16, 32, 64, 128};
const int X_TABLE = B[4] + B[5] + B[6] + B[7];
const int Y_TABLE = B[2] + B[3] + B[6] + B[7];
const int Z_TABLE = B[1] + B[3] + B[5] + B[7];
string dp[1 << 8][3];
void add(int pr, const string& s, int mask) {
if (dp[mask][pr].empty() || ls(s, dp[mask][pr])) {
dp[mask][pr] = s;
Expression e(s, mask, pr);
q.insert(e);
}
}
int main() {
add(2, "x", X_TABLE);
add(2, "y", Y_TABLE);
add(2, "z", Z_TABLE);
while (!q.empty()) {
auto e = *q.begin();
q.erase(q.begin());
if (e.p == 2) {
add(2, "!" + e.e, ~e.t & FULL);
add(1, e.e, e.t);
}
if (e.p == 1) {
for (int mask = 0; mask < FULL; ++mask) {
if (!dp[mask][2].empty()) {
add(1, dp[mask][2] + "&" + e.e, mask & e.t);
add(1, e.e + "&" + dp[mask][2], mask & e.t);
}
}
add(2, "(" + e.e + ")", e.t);
add(0, e.e, e.t);
}
if (e.p == 0) {
for (int mask = 0; mask < FULL; ++mask) {
for (int pr = 1; pr <= 2; ++pr) {
if (!dp[mask][pr].empty()) {
add(0, dp[mask][pr] + "|" + e.e, mask | e.t);
add(0, e.e + "|" + dp[mask][pr], mask | e.t);
}
}
}
add(2, "(" + e.e + ")", e.t);
}
}
int n;
cin >> n;
while (n--) {
string s;
cin >> s;
int mask = 0;
for (int i = 0; i < 8; ++i) {
if (s[i] == '1') {
mask |= (1 << i);
}
}
cout << dp[mask][0] << endl;
}
return 0;
}
Solution 2
#include <bits/stdc++.h>
using namespace std;
string res[256][3];
bool changed;
void update(string &a, string &b) {
if (a == "" || (b.length() < a.length() || (b.length() == a.length() && b < a))) {
changed = true;
a = b;
}
}
int main() {
res[(1 << 4) + (1 << 5) + (1 << 6) + (1 << 7)][0] = "x";
res[(1 << 2) + (1 << 3) + (1 << 6) + (1 << 7)][0] = "y";
res[(1 << 1) + (1 << 3) + (1 << 5) + (1 << 7)][0] = "z";
changed = true;
while (changed) {
changed = false;
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 3; j++) {
if (res[i][j] == "") {
continue;
}
{ // op == 0
string s = res[i][j];
if (j > 0) {
s = "(" + s + ")";
}
s = "!" + s;
update(res[i ^ 255][0], s);
}
for (int ii = 0; ii < 256; ii++) {
for (int jj = 0; jj < 3; jj++) {
if (res[ii][jj] == "") {
continue;
}
for (int op = 1; op <= 2; op++) {
string s = res[i][j];
if (j > op) {
s = "(" + s + ")";
}
string t = res[ii][jj];
if (jj > op) {
t = "(" + t + ")";
}
string w = s + (op == 1 ? '&' : '|') + t;
update(res[op == 1 ? (i & ii) : (i | ii)][op], w);
}
}
}
}
}
}
int tt;
cin >> tt;
while (tt--) {
string z;
cin >> z;
int mask = 0;
for (int i = 0; i < 8; i++) {
mask |= (z[i] - '0') << i;
}
string best = "";
for (int j = 0; j < 3; j++) {
update(best, res[mask][j]);
}
cout << best << endl;
}
return 0;
}
Strongly Connected Tournament
Problem writer: YakutovDmitriy
Tutorial is loading...
Solution
#include <bits/stdc++.h>
using namespace std;
const int md = 998244353;
inline void add(int &a, int b) {
a += b;
if (a >= md) a -= md;
}
inline void sub(int &a, int b) {
a -= b;
if (a < 0) a += md;
}
inline int mul(int a, int b) {
return (int) ((long long) a * b % md);
}
inline int power(int a, long long b) {
int res = 1;
while (b > 0) {
if (b & 1) {
res = mul(res, a);
}
a = mul(a, a);
b >>= 1;
}
return res;
}
inline int inv(int a) {
return power(a, md - 2);
}
int main() {
int n, P, Q;
cin >> n >> P >> Q;
int p = mul(P, inv(Q));
vector< vector<int> > p_win(n + 1, vector<int>(n + 1, 0));
p_win[0][0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
add(p_win[i + 1][j], mul(p_win[i][j], power(p, j)));
add(p_win[i + 1][j + 1], mul(p_win[i][j], power((1 - p + md) % md, i - j)));
}
}
vector<int> p_strong(n + 1);
for (int i = 1; i <= n; i++) {
p_strong[i] = 1;
for (int j = 1; j < i; j++) {
sub(p_strong[i], mul(p_strong[j], p_win[i][j]));
}
}
vector<int> res(n + 1);
res[1] = 0;
for (int i = 2; i <= n; i++) {
res[i] = 0;
for (int j = 1; j < i; j++) {
int coeff = mul(p_strong[j], p_win[i][j]);
int games = (res[j] + res[i - j]) % md;
add(games, j * (j - 1) / 2 + j * (i - j));
add(res[i], mul(coeff, games));
}
add(res[i], mul(i * (i - 1) / 2, p_strong[i]));
res[i] = mul(res[i], inv((1 - p_strong[i] + md) % md));
}
cout << res[n] << endl;
return 0;
}
Power Substring
Problem writer: YakutovDmitriy
Tutorial is loading...
Python solution
def dlog(x, n):
bigMod = 5 ** n
ans = [None, 0, 1, 3, 2][x % 5]
val = 2 ** ans % bigMod
mod, phi = 5, 4
phiVal = 2 ** phi % bigMod
for i in range(2, n + 1):
nextMod = mod * 5
while val % nextMod != x % nextMod:
val = val * phiVal % bigMod
ans += phi
phi *= 5
phiVal = (phiVal *
phiVal % bigMod *
phiVal % bigMod *
phiVal % bigMod *
phiVal % bigMod)
mod = nextMod
return ans
def main():
inp = input()
n = len(inp)
a = int(inp)
for m in range(n + 1):
l = a * 10 ** m
x, mod = l, 2 ** (n + m)
if x % mod != 0:
x += mod - x % mod
if x % 5 == 0:
x += mod
if x < l + 10 ** m:
assert x % mod == 0 and x % 5 != 0
x = x // mod
mod = 5 ** (n + m)
print(n + m + dlog(x % mod, n + m))
return
assert False
if __name__ == '__main__':
cnt = int(input())
for i in range(cnt):
main()
C++ solution
#include <bits/stdc++.h>
using namespace std;
inline long long mul(long long a, long long b, long long md) {
long long res = 0;
while (b > 0) {
if (b & 1) {
res += a; if (res >= md) res -= md;
}
a += a; if (a >= md) a -= md;
b >>= 1;
}
return res;
}
inline long long power(long long a, long long b, long long md) {
long long res = 1;
while (b > 0) {
if (b & 1) {
res = mul(res, a, md);
}
a = mul(a, a, md);
b >>= 1;
}
return res;
}
int main() {
int tt;
cin >> tt;
while (tt--) {
long long a;
cin >> a;
int n = (int) to_string(a).length();
for (int m = 0; ; m++) {
long long b = (-a) & ((1LL << (n + m)) - 1);
if ((a + b) % 5 == 0) {
b += (1LL << (n + m));
}
if ((b == 0 && m == 0) || (int) to_string(b).length() <= m) {
long long c = (a + b) >> (n + m);
long long t = vector<long long>{-1, 0, 1, 3, 2}[c % 5];
long long p5 = 5;
for (int i = 1; i < n + m; i++) {
while (power(2, t, p5 * 5) != c % (p5 * 5)) {
t += p5 / 5 * 4;
}
p5 *= 5;
}
t += n + m;
cout << t << endl;
break;
}
a *= 10;
}
}
return 0;
}
Don't Exceed
Problem writer: tourist
Tutorial is loading...
O(n^5) solution
#include <bits/stdc++.h>
using namespace std;
const int md = 998244353;
inline void add(int &a, int b) {
a += b;
if (a >= md) a -= md;
}
inline void sub(int &a, int b) {
a -= b;
if (a < 0) a += md;
}
inline int mul(int a, int b) {
return (int) ((long long) a * b % md);
}
inline int power(int a, long long b) {
int res = 1;
while (b > 0) {
if (b & 1) {
res = mul(res, a);
}
a = mul(a, a);
b >>= 1;
}
return res;
}
inline int inv(int a) {
return power(a, md - 2);
}
const int N = 77;
int C[N][N];
typedef vector<int> poly;
poly integrate(poly a) {
poly b = {0};
for (int i = 0; i < (int) a.size(); i++) {
b.push_back(mul(a[i], inv(i + 1)));
}
return b;
}
void sub(poly &a, poly b) {
while (a.size() < b.size()) {
a.push_back(0);
}
for (int i = 0; i < (int) b.size(); i++) {
sub(a[i], b[i]);
}
}
poly plug(poly a, int delta) {
// a(x + delta)
poly b(a.size(), 0);
for (int i = 0; i < (int) a.size(); i++) {
for (int j = 0; j <= i; j++) {
add(b[j], mul(a[i], mul(C[i][j], power(delta, i - j))));
}
}
return b;
}
int eval(poly a, int x) {
int res = 0;
for (int i = (int) a.size() - 1; i >= 0; i--) {
res = mul(res, x);
add(res, a[i]);
}
return res;
}
const int COEFF = 1000000;
int main() {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
C[i][j] = (j == 0 ? 1 : (i == 0 ? 0 : (C[i - 1][j] + C[i - 1][j - 1]) % md));
}
}
int n;
cin >> n;
vector<int> x(n), fracs;
for (int i = 0; i < n; i++) {
double foo;
cin >> foo;
x[i] = (int) (foo * COEFF + 0.5);
fracs.push_back(x[i] % COEFF);
}
fracs.push_back(0);
sort(fracs.begin(), fracs.end());
fracs.resize(unique(fracs.begin(), fracs.end()) - fracs.begin());
int cnt = (int) fracs.size();
vector<int> point(n * cnt + 1);
for (int i = 0; i <= n * cnt; i++) {
point[i] = mul(i / cnt * COEFF + fracs[i % cnt], inv(COEFF));
}
vector<int> cut(n);
for (int i = 0; i < n; i++) {
cut[i] = (int) (find(point.begin(), point.end(), mul(x[i], inv(COEFF))) - point.begin());
}
vector<poly> a(n * cnt);
for (int i = 0; i < n * cnt; i++) {
a[i] = {i < min(cnt, cut[0]) ? 1 : 0};
}
for (int id = 1; id < n; id++) {
for (int i = 0; i < n * cnt; i++) {
a[i] = integrate(a[i]);
}
for (int i = n * cnt - 1; i >= 0; i--) {
sub(a[i][0], eval(a[i], point[i]));
for (int j = i - 1; j >= i - cnt && j >= 0; j--) {
add(a[i][0], eval(a[j], point[j + 1]));
if (j > i - cnt) {
sub(a[i][0], eval(a[j], point[j]));
} else {
sub(a[i], plug(a[i - cnt], md - 1));
}
}
}
for (int i = cut[id]; i < n * cnt; i++) {
a[i] = {0};
}
}
int ans = 0;
for (int i = 0; i < n * cnt; i++) {
poly b = integrate(a[i]);
add(ans, eval(b, point[i + 1]));
sub(ans, eval(b, point[i]));
}
printf("%d\n", ans);
return 0;
}
O(n^4) solution
#include <bits/stdc++.h>
using namespace std;
const int md = 998244353;
inline void add(int &a, int b) {
a += b;
if (a >= md) a -= md;
}
inline void sub(int &a, int b) {
a -= b;
if (a < 0) a += md;
}
inline int mul(int a, int b) {
return (int) ((long long) a * b % md);
}
inline int power(int a, long long b) {
int res = 1;
while (b > 0) {
if (b & 1) {
res = mul(res, a);
}
a = mul(a, a);
b >>= 1;
}
return res;
}
inline int inv(int a) {
return power(a, md - 2);
}
typedef vector<int> poly;
poly integrate(poly a) {
poly b = {0};
for (int i = 0; i < (int) a.size(); i++) {
b.push_back(mul(a[i], inv(i + 1)));
}
return b;
}
void sub(poly &a, poly b) {
while (a.size() < b.size()) {
a.push_back(0);
}
for (int i = 0; i < (int) b.size(); i++) {
sub(a[i], b[i]);
}
}
int eval(poly a, int x) {
int res = 0;
for (int i = (int) a.size() - 1; i >= 0; i--) {
res = mul(res, x);
add(res, a[i]);
}
return res;
}
const int COEFF = 1000000;
int main() {
int n;
cin >> n;
vector<int> x(n), fracs;
for (int i = 0; i < n; i++) {
double foo;
cin >> foo;
x[i] = (int) (foo * COEFF + 0.5);
fracs.push_back(x[i] % COEFF);
}
fracs.push_back(0);
sort(fracs.begin(), fracs.end());
fracs.resize(unique(fracs.begin(), fracs.end()) - fracs.begin());
int cnt = (int) fracs.size();
vector<int> point(n * cnt + 1);
for (int i = 0; i <= n * cnt; i++) {
point[i] = i / cnt * COEFF + fracs[i % cnt];
}
vector<int> cut(n);
for (int i = 0; i < n; i++) {
cut[i] = (int) (find(point.begin(), point.end(), x[i]) - point.begin());
}
vector<int> sz(n * cnt);
for (int i = 0; i < n * cnt; i++) {
sz[i] = mul((point[i + 1] - point[i] + md) % md, inv(COEFF));
}
vector<poly> a(n * cnt);
vector<int> sum(n * cnt);
for (int i = 0; i < n * cnt; i++) {
a[i] = i < min(cnt, cut[0]) ? vector<int>{0, 1} : vector<int>{0};
sum[i] = a[i].size() == 1 ? 0 : sz[i];
}
for (int id = 1; id < n; id++) {
for (int i = n * cnt - 1; i >= 0; i--) {
if (i >= cut[id]) {
a[i] = {0};
sum[i] = 0;
} else {
for (int j = i - 1; j >= i - cnt && j >= 0; j--) {
add(a[i][0], sum[j]);
}
if (i - cnt >= 0) {
sub(a[i], a[i - cnt]);
}
a[i] = integrate(a[i]);
sum[i] = eval(a[i], sz[i]);
}
}
}
int ans = 0;
for (int i = 0; i < n * cnt; i++) {
add(ans, sum[i]);
}
printf("%d\n", ans);
return 0;
}