给出球拍和手套的价格,哪个贵买哪个,要求输出购买的物品。
判断输出即可。
#include
using namespace std;
typedef long long LL;
const int N = 2e5 + 5e2;
void solve() {
int B, G;
cin >> B >> G;
if (B > G) {
cout << "Bat" << endl;
} else {
cout << "Glove" << endl;
}
}
int main() {
int Case = 1;
while (Case--) {
solve();
}
return 0;
}
有一条无限长的路,路上的 A A A种了一棵树,并以 A A A点为中心,每隔 k k k米均有一棵树,问 L ∼ R L \sim R L∼R之间共有多少棵树(包含边界)。
首先可以通过将区间左右端点减去 A A A,此时中心点就变为了原点。
然后考虑两种情况:
左右边界均在原点一侧
左右边界在原点两侧
如果左右边界在原点一侧,可以直接通过计算得到区间内的树的数量(左右边界均为负数时可以以原点为中心翻转)
如果左右边界在原点两侧,那么可以分别计算两边到原点之间有多少棵树。
#include
using namespace std;
typedef long long LL;
const int N = 2e5 + 5e2;
void solve() {
LL A, M, L, R;
cin >> A >> M >> L >> R;
L -= A, R -= A;
LL ans = 0;
if (L < 0 && R < 0) {
L = -L, R = -R;
swap(L, R);
}
if (L >= 0) {
ans = R / M - L / M;
if (L % M == 0) ans++;
} else {
ans = R / M + (-L) / M + 1;
}
cout << ans << endl;
}
int main() {
int Case = 1;
while (Case--) {
solve();
}
return 0;
}
有 N N N双袜子,编号为 1 ∼ N 1 \sim N 1∼N,其中有 k k k双袜子丢失了,编号为 A 1 , A 2 , . . . , A k A_1, A_2, ..., A_k A1,A2,...,Ak,当穿上两只不同的袜子时,古怪值为这两只袜子编号之差的绝对值,问,如果将剩下的袜子两两配对(如果总数为奇数,可以丢掉一只袜子),最小的古怪值是多少。
对于没有发生丢失的袜子,不需要进行操作。
对于发生丢失的袜子,分为两种情况:
丢失的袜子数量为偶数
丢失的袜子数量为奇数
当丢失的袜子数量为偶数时,由于给出的袜子编号是有序的,那么将袜子按顺序进行匹配,古怪值为 ( A 2 − A 1 ) + . . . + ( A k − A k − 1 ) (A_2 - A_1) + ... + (A_k - A_{k - 1}) (A2−A1)+...+(Ak−Ak−1)。
当丢失的袜子数量为奇数时,由于无法知道丢掉哪只袜子是最优的,因此,可以对丢掉的袜子进行枚举,丢掉一只袜子后,剩余的袜子按偶数的情况进行计算,为了避免超时,可以预处理前缀和和后缀和,如果前后两段袜子数量恰好为奇数,那么就让前一段的最后一只袜子与后一段的第一只袜子匹配即可。
#include
using namespace std;
typedef long long LL;
const int N = 2e5 + 5e2;
int a[N], L[N], R[N];
void solve() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= k; i++) cin >> a[i];
int ans = 0;
for (int i = 1; i <= k; i += 2) {
ans += a[i + 1] - a[i];
}
L[2] = a[2] - a[1];
for (int i = 4; i < k; i += 2) {
L[i] = a[i] - a[i - 1] + L[i - 2];
}
for (int i = k - 1; i >= 1; i -= 2) {
R[i] = a[i + 1] - a[i] + R[i + 2];
}
if (k % 2 == 1) {
int res = 1e9;
for (int i = 1; i <= k; i++) {
if (i % 2 == 1) {
if (i == 1) res = min(res, R[i + 1]);
else res = min(res, L[i - 1] + R[i + 1]);
} else {
int num = L[i - 2] + R[i + 2] + a[i + 1] - a[i - 1];
res = min(res, num);
}
}
cout << res << endl;
} else {
cout << ans << endl;
}
}
int main() {
int Case = 1;
while (Case--) {
solve();
}
return 0;
}
有 N N N个雪橇,第 i i i个雪橇需要 R i R_i Ri头驯鹿才能拉动。
有 Q Q Q个询问,每个询问会给出一个正整数 X X X,问有 X X X头驯鹿时最多可以拉动多少个雪橇。
既然想要拉动的雪橇数量尽可能多,那么应该从小到大的选择雪橇需要的驯鹿数量,因此可以先对需要的驯鹿数量排序,然后维护前缀和,之后的查询使用二分来进行。
#include
using namespace std;
typedef long long LL;
const int N = 2e5 + 5e2;
LL R[N], pre[N];
void solve() {
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> R[i];
}
sort(R + 1, R + n + 1);
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + R[i];
}
while (q--) {
LL x;
cin >> x;
int l = 0, r = n, ans = 0;
while (l <= r) {
int mid = l + r >> 1;
if (pre[mid] <= x) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
cout << ans << endl;
}
}
int main() {
int Case = 1;
while (Case--) {
solve();
}
return 0;
}
有一个 H H H行 W W W列的网格,其中每个单元格被涂成红色或绿色。
设 ( i , j ) (i,j) (i,j)表示从上到下第 i i i行,从左到右第 j j j列的单元格。
单元格 ( i , j ) (i,j) (i,j)的颜色由字符 S i , j S_{i,j} Si,j表示, S i , j = " . " S_{i,j}="." Si,j="."表示单元格 ( i , j ) (i,j) (i,j)是红色的, S i , j = " . " S_{i,j}="." Si,j="."表示单元格 ( i , j ) (i,j) (i,j)是绿色的。
定义绿色连通分量是指顶点集是绿色单元格、边缘集为连接两个相邻绿色单元格的单元格的集合。当 ∣ x − x ′ ∣ + ∣ y − y ′ ∣ = 1 \lvert x−x^′\rvert + \lvert y−y^′\rvert=1 ∣x−x′∣+∣y−y′∣=1时,单元格 ( x , y ) (x,y) (x,y)和 ( x ′ , y ′ ) (x',y') (x′,y′)被认为是相邻的。
选择一个红色单元格并随机地将其重新涂成绿色。计算重新涂色后网格中绿色连通分量数量的期望值,结果对 998244353 998244353 998244353取模。
对于每个红色方块,考虑将其重新涂成绿色后连通分量数量的差异。
固定一个红色方块 ( i , j ) (i,j) (i,j),假设有 x x x个绿色连通分量与单元格 ( i , j ) (i,j) (i,j)相邻。通过将 ( i , j ) (i,j) (i,j)涂成绿色,所有与 ( i , j ) (i,j) (i,j)相邻的绿色方块都与之相连,因此包含 ( i , j ) (i,j) (i,j)或者与之相邻的方块的绿色联通分量数量从 x x x变为 1 1 1。其他地方的连通分量数量不变,所以总数减少了 ( x − 1 ) (x-1) (x−1)个。(当 x = 0 x=0 x=0 时,可以认为是减少了 − 1 -1 −1个,即增加了 1 1 1个)。
由于网格大小只有 1000 × 1000 1000 \times 1000 1000×1000,因此可以枚举每个红色单元格,分别计算其涂色后的影响,结果求平均值即可,可以使用并查集或者 D F S DFS DFS进行维护。
#include
using namespace std;
typedef long long LL;
const int MAXN = 1005;
const LL mod = 998244353;
char c[MAXN][MAXN];
LL a[MAXN][MAXN], cnt, n, m;
void dfs(int i, int j) {
if (a[i][j] || c[i][j] != '#')
return;
a[i][j] = cnt;
dfs(i + 1, j);
dfs(i, j + 1);
dfs(i - 1, j);
dfs(i, j - 1);
}
int gt(int x, int y) {
if (x > n || x < 1 || y > m || y < 1 || c[x][y] == '.')
return 0;
return a[x][y];
}
int get(int x, int y) {
map<int, int> mp;
if (gt(x + 1, y))
mp[gt(x + 1, y)] = 1;
if (gt(x, y + 1))
mp[gt(x, y + 1)] = 1;
if (gt(x - 1, y))
mp[gt(x - 1, y)] = 1;
if (gt(x, y - 1))
mp[gt(x, y - 1)] = 1;
return 1 - mp.size();
}
void exgcd(LL a, LL b, LL &x, LL &y) {
if (!b) {
x = 1;
y = 0;
} else {
exgcd(b, a % b, y, x);
y -= a / b * x;
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> c[i][j];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (c[i][j] == '#' && !a[i][j]) {
++cnt, dfs(i, j);
}
}
}
LL p = 0, q = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (c[i][j] == '.') {
q++;
p += cnt + get(i, j);
p %= mod;
}
}
}
LL k = __gcd(p, q);
p /= k;
q /= k;
LL x, y;
exgcd(q, mod, x, y);
x = (x % mod + mod) % mod;
cout << (x * p) % mod << endl;
return 0;
}
圣诞老人住在一个用平面坐标系 x y xy xy表示的小镇上,小镇有 N N N个孩子,编号为 1 1 1到 N N N。圣诞老人的家坐标为 ( S X , S Y ) (S_X,S_Y) (SX,SY),孩子 i i i ( 1 ≤ i ≤ N ) (1\le i \le N) (1≤i≤N)的家在坐标 ( X i , Y i ) (X_i,Y_i) (Xi,Yi)。
圣诞老人想按数字的顺序给 N N N个孩子每人送一份礼物。为了给孩子 i i i送礼物,圣诞老人必须带着至少一件礼物去拜访孩子 i i i的家。然而,圣诞老人一次最多只能携带 K K K个礼物,把身上的礼物送完后,他必须回到自己的家补充礼物(圣诞老人家里有足够的礼物)。
求出圣诞老人离开家,给所有 N N N个孩子送礼物,然后返回家的最小路程。
对于每个孩子 i i i,在给孩子 i i i送礼物之后和给孩子 ( i + 1 ) (i+1) (i+1)送礼物之前有两条可能的路径:
用序列 d i d_i di,表示从圣诞老人家走到第 i i i个点的距离, s u m ( i → j ) sum(i→j) sum(i→j)表示从房子 i i i走到房子 j j j的距离。
采用动态规划对其进行求解。令 d p i dp_i dpi表示前 i i i个孩子走完的最小花费。枚举 j j j, d p i = m i n [ d p j + d ( j + 1 ) + d ( i ) + s u m ( j + 1 → i ) ] dp_i=min[dp_j+d(j+1)+d(i)+sum(j+1→i)] dpi=min[dpj+d(j+1)+d(i)+sum(j+1→i)]。因为圣诞老人最多可以携带 K K K个礼物,所以 ( i − j ≤ k ) (i−j≤k) (i−j≤k)。可以使用单调队列或者线段树进行优化。
#include
using namespace std;
typedef long long LL;
const int MAXN = 3e5 + 5;
LL a[MAXN];
double d[MAXN], dp[MAXN], s[MAXN], sum[MAXN];
struct edge {
double x, y;
} ed[MAXN];
double solve(double a, double b, double c, double d) {
return sqrt((a - c) * (a - c) + (b - d) * (b - d));
}
int main() {
int n, c;
double sx, sy;
cin >> n >> c >> sx >> sy;
for (int i = 1; i <= n; i++)
cin >> ed[i].x >> ed[i].y;
for (int i = 1; i <= n; i++)
dp[i] = 0x3f3f3f3f;
dp[0] = 0;
ed[0].x = sx;
ed[0].y = sy;
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1] + solve(ed[i - 1].x, ed[i - 1].y, ed[i].x, ed[i].y);
d[i] = solve(sx, sy, ed[i].x, ed[i].y);
}
int hd, tl;
hd = tl = 1;
a[1] = 0;
for (int i = 1; i <= n; i++) {
while (hd <= tl && i - a[hd] > c)
hd++;
if (hd <= tl)
dp[i] = dp[a[hd]] + d[i] + d[a[hd] + 1] + sum[i] - sum[a[hd] + 1];
while (hd <= tl && dp[a[tl]] + d[a[tl] + 1] - sum[a[tl] + 1] > dp[i] + d[i + 1] - sum[i + 1])
tl--;
a[++tl] = i;
}
cout << fixed << setprecision(8) << dp[n] << endl;
return 0;
}
以下为学习交流QQ群,群号: 546235402,每周题解完成后都会转发到群中,大家可以加群一起交流做题思路,分享做题技巧,欢迎大家的加入。