Идея: BledDest
t = int(input())
for i in range(t):
n, m, k = map(int, input().split())
d = n // k
a1 = min(m, d)
a2 = (m - a1 + k - 2) // (k - 1)
print(a1 - a2)
t = int(input())
for i in range(t):
n, m, k = map(int, input().split())
ans = 0
d = n // k
for a1 in range(m + 1):
for a2 in range(a1 + 1):
if(a1 > d):
continue
if(a1 + a2 > m):
continue
if(a1 + (k - 1) * a2 < m):
continue
ans = max(ans, a1 - a2)
print(ans)
Идея: BledDest
t = int(input())
for _ in range(t):
n, m, x, y = map(int, input().split())
ans = 0
y = min(y, 2 * x)
for __ in range(n):
s = input()
i = 0
while i < m:
if s[i] == '*':
i += 1
continue
j = i
while j + 1 < m and s[j + 1] == '.':
j += 1
l = j - i + 1
ans += l % 2 * x + l // 2 * y
i = j + 1
print(ans)
Идея: adedalic
Рассмотрим два типа остановок: $$$k$$$ горячих и $$$k$$$ холодных кружек и $$$(k + 1)$$$ горячая и $$$k$$$ холодных кружек.
Первый случай тривиален: температура всегда равна $$$\frac{h + c}{2}$$$. Во втором случае температура всегда строго выше, чем $$$\frac{h + c}{2}$$$. Поэтому, если $$$t \le \frac{h + c}{2}$$$, то ответ всегда $$$2$$$.
Покажем, что в противном случае ответ всегда достигается из второго случая:
Температура после $$$(k + 1)$$$ горячей кружки и $$$k$$$ холодных кружек $$$t_k = \frac{(k + 1) \cdot h + k \cdot c}{2k + 1}$$$. Утверждается, что $$$t_0 > t_1 > \dots$$$. Докажем это по индукции.
$$$t_0 = h, t_1 = \frac{2 \cdot h + c}{3}$$$. $$$c < h$$$, поэтому $$$t_0 > t_1$$$.
Теперь сравним $$$t_k$$$ и $$$t_{k+1}$$$.
Также стоит показать, что этот ряд сходится к $$$\frac{h + c}{2}$$$:
Извиняюсь, что я не очень силен в матанализе, но моя интуиция подсказывает мне, что надо показать, что $$$\forall k~t_k > \frac{h + c}{2}$$$ и $$$\forall \varepsilon \exists k~t_k < \frac{h + c}{2}$$$ при $$$k \ge 0$$$.
Так что первая часть:
И вторая часть:
Так что это утверждение показывает нам, что для любого $$$t$$$, больше чем $$$\frac{h + c}{2}$$$, ответ всегда достигается из второго случая.
Это позволяет нам найти такое $$$k$$$, что значение $$$t_k$$$ ровно $$$t$$$. Однако, $$$k$$$ не всегда оказывается целым числом. $$$\frac{(k + 1) \cdot h + c}{2k + 1} = t \leftrightarrow$$$ $$$\frac{k \cdot (h + c) + h}{2k + 1} = t \leftrightarrow$$$ $$$k \cdot (h + c) + h = 2kt + t \leftrightarrow$$$ $$$k \cdot (h + c - 2t) = t - h \leftrightarrow$$$ $$$k = \frac{t - h}{h + c - 2t}$$$.
Остается только понять, в какую сторону выгоднее округлять $$$k$$$. Кажется, что некоторые реализации с вещественными числами могут не работать из-за погрешностей вычислений. Однако, можно все целиком провести в целых числах.
Перепишем это выражение, чтобы знаменатель был всегда положительным $$$k = \frac{h - t}{2t - h - c}$$$. Теперь округлим это значение вниз и сравним $$$k$$$ и $$$k + 1$$$.
Оптимальное значение достигается при $$$k$$$, если $$$|\frac{k \cdot (h + c) + h}{2k + 1} - t| \le |\frac{(k + 1) \cdot (h + c) + h}{2k + 3}| - t$$$. Так что $$$|(k \cdot (h + c) + h) - t \cdot (2k + 1)| \cdot (2k + 3) \le |((k + 1) \cdot (h + c) + h) - t \cdot (2k + 3)| \cdot (2k + 1)$$$. Иначе ответ $$$k + 1$$$.
Оптимальное значение $$$k$$$ можно также найти бинарным поиском, но формулы получаются такие же, и все равно приходится опираться на монотонность. К тому же формулы помогают определить верхнюю границу на ответ.
Асимптотика решения: $$$O(1)$$$ или $$$O(\log h)$$$ на набор входных данных.
#include <bits/stdc++.h>
#define forn(i, n) for (int i = 0; i < int(n); i++)
using namespace std;
int main() {
int tc;
scanf("%d", &tc);
forn(_, tc){
int h, c, t;
scanf("%d%d%d", &h, &c, &t);
if (h + c - 2 * t >= 0)
puts("2");
else{
int a = h - t;
int b = 2 * t - c - h;
int k = 2 * (a / b) + 1;
long long val1 = abs(k / 2 * 1ll * c + (k + 1) / 2 * 1ll * h - t * 1ll * k);
long long val2 = abs((k + 2) / 2 * 1ll * c + (k + 3) / 2 * 1ll * h - t * 1ll * (k + 2));
printf("%d\n", val1 * (k + 2) <= val2 * k ? k : k + 2);
}
}
return 0;
}
1359D - Yet Another Yet Another Task
Идея: BledDest
#include <bits/stdc++.h>
#define forn(i, n) for (int i = 0; i < int(n); i++)
using namespace std;
const int INF = 1e9;
int main() {
int n;
scanf("%d", &n);
vector<int> a(n);
forn(i, n) scanf("%d", &a[i]);
long long ans = 0;
forn(mx, 31){
long long cur = 0;
long long best = 0;
forn(i, n){
int val = (a[i] > mx ? -INF : a[i]);
cur += val;
best = min(best, cur);
ans = max(ans, (cur - best) - mx);
}
}
printf("%lld\n", ans);
return 0;
}
Идея: BledDest
#include<bits/stdc++.h>
using namespace std;
const int N = 500043;
const int MOD = 998244353;
int fact[N];
int add(int x, int y)
{
x += y;
while(x >= MOD) x -= MOD;
while(x < 0) x += MOD;
return x;
}
int mul(int x, int y)
{
return (x * 1ll * y) % MOD;
}
int binpow(int x, int y)
{
int z = 1;
while(y > 0)
{
if(y % 2 == 1)
z = mul(z, x);
x = mul(x, x);
y /= 2;
}
return z;
}
int inv(int x)
{
return binpow(x, MOD - 2);
}
int divide(int x, int y)
{
return mul(x, inv(y));
}
void precalc()
{
fact[0] = 1;
for(int i = 1; i < N; i++)
fact[i] = mul(i, fact[i - 1]);
}
int C(int n, int k)
{
if(k > n) return 0;
return divide(fact[n], mul(fact[n - k], fact[k]));
}
int main()
{
int n, k;
cin >> n >> k;
int ans = 0;
precalc();
for(int i = 1; i <= n; i++)
{
int d = n / i;
ans = add(ans, C(d - 1, k - 1));
}
cout << ans << endl;
}
Идея: BledDest
#include <bits/stdc++.h>
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define x first
#define y second
using namespace std;
const double INF = 1e13;
struct line{
int A, B, C;
line(){}
line(int x1, int y1, int x2, int y2){
A = y1 - y2;
B = x2 - x1;
C = -A * x1 - B * y1;
// A is guaranteed to be non-zero
if (A < 0) A = -A, B = -B, C = -C;
int g = __gcd(A, __gcd(abs(B), abs(C)));
A /= g, B /= g, C /= g;
}
};
bool operator ==(const line &a, const line &b){
return a.A == b.A && a.B == b.B && a.C == b.C;
}
double x;
bool operator <(const line &a, const line &b){
double val1 = (-a.A * x - a.C) / a.B;
double val2 = (-b.A * x - b.C) / b.B;
return val1 < val2;
}
struct car{
int x, y, dx, dy, s;
line l;
double vx, vy;
};
int n;
vector<car> a(n);
long long det(int a, int b, int c, int d){
return a * 1ll * d - b * 1ll * c;
}
bool inter(const line &a, const line &b, long long &D, long long &Dx, long long &Dy){
D = det(a.A, a.B, b.A, b.B);
if (D == 0) return false;
Dx = -det(a.C, a.B, b.C, b.B);
Dy = -det(a.A, a.C, b.A, b.C);
return true;
}
int sg(int x){
return x < 0 ? -1 : 1;
}
int sg(long long a, long long b, int c){
// sign of a/b-c
if (b < 0) a = -a, b = -b;
return a - c * b < 0 ? -1 : (a - c * b > 0);
}
bool inter(int i, int j, double &len){
if (i == -1 || j == -1)
return false;
long long D, Dx, Dy;
if (!inter(a[i].l, a[j].l, D, Dx, Dy))
return false;
if (sg(Dx, D, a[i].x) != 0 && sg(a[i].dx) != sg(Dx, D, a[i].x))
return false;
if (sg(Dx, D, a[j].x) != 0 && sg(a[j].dx) != sg(Dx, D, a[j].x))
return false;
double x = Dx / double(D);
double y = Dy / double(D);
double di = (a[i].x - x) * (a[i].x - x) + (a[i].y - y) * (a[i].y - y);
double dj = (a[j].x - x) * (a[j].x - x) + (a[j].y - y) * (a[j].y - y);
return len * len >= di / a[i].s && len * len >= dj / a[j].s;
}
vector<set<pair<line, int>>::iterator> del;
set<pair<line, int>> q;
void get_neighbours(int i, int &l, int &r){
l = r = -1;
auto it = q.lower_bound({a[i].l, -1});
if (it != q.end())
r = it->y;
if (!q.empty() && it != q.begin()){
--it;
l = it->y;
}
}
bool check(double t){
vector<pair<double, pair<int, int>>> cur;
del.resize(n);
forn(i, n){
double x1 = a[i].x;
double x2 = a[i].x + a[i].vx * t;
if (x1 > x2) swap(x1, x2);
cur.push_back({x1, {i, 0}});
cur.push_back({x2, {i, 1}});
}
q.clear();
sort(cur.begin(), cur.end());
for (auto &qr : cur){
x = qr.x;
int i = qr.y.x;
int l, r;
if (qr.y.y == 0){
get_neighbours(i, l, r);
if (r != -1 && a[i].l == a[r].l)
return true;
if (inter(i, l, t))
return true;
if (inter(i, r, t))
return true;
del[i] = q.insert({a[i].l, i}).x;
}
else{
q.erase(del[i]);
get_neighbours(i, l, r);
if (inter(l, r, t))
return true;
}
}
return false;
}
int main() {
scanf("%d", &n);
a.resize(n);
forn(i, n){
scanf("%d%d%d%d%d", &a[i].x, &a[i].y, &a[i].dx, &a[i].dy, &a[i].s);
a[i].l = line(a[i].x, a[i].y, a[i].x + a[i].dx, a[i].y + a[i].dy);
double d = sqrt(a[i].dx * a[i].dx + a[i].dy * a[i].dy);
a[i].vx = a[i].dx / d * a[i].s;
a[i].vy = a[i].dy / d * a[i].s;
a[i].s *= a[i].s;
}
double l = 0, r = INF;
bool ok = false;
forn(_, 100){
double m = (l + r) / 2;
if (check(m)){
ok = true;
r = m;
}
else{
l = m;
}
}
if (!ok)
puts("No show :(");
else
printf("%.15lf\n", l);
return 0;
}