由于作者代码风格有变,头文件较长,以下代码均舍去头文件。
abc257_a
题目翻译
给定一个 $n$,生成一个字符串,内容为 $n$ 个 $\tt{A}$,$n$ 个 $\tt{B}$,一直到 $n$ 个 $\tt{Z}$。
输出第 $k$ 位。
题目思路
直接模拟到第 $n$ 位。
这是最暴力的写法。
也可以用数学知识算一下当前是哪个字符。
我采用了最暴力的。
AC 代码
int main()
{
int n, x, cnt = 0;
cin >> n >> x;
for (int i = 1; i <= 26; i++)
{
for (int j = 1; j <= n; j++)
{
cnt++;
if (cnt == x)
{
cout << char (i + 'A' - 1) << endl;
return 0;
}
}
}
return 0;
}
abc257_b
题目翻译
有个长度为 $n$ 的道路,第 $a_i$ 个位置上有一个士兵。
有 $Q$ 次操作,第 $i$ 次操作将第 $l_i$ 个士兵往右一位。
如果自己是最后一个位置或者右边有人,不移动。
输出士兵位置。
题目思路
模拟。
由于 $n\leq100,Q \leq1000$,每次扫一遍不超时。
AC 代码
int a[205];
int main()
{
int n, k, q;
cin >> n >> k >> q;
for (int i = 1; i <= k; i++)
{
int x;
cin >> x;
a[x] = 1;
}
for (int i = 1; i <= q; i++)
{
int l, cnt = 0;
cin >> l;
for (int j = 1; j <= n; j++)
{
if (a[j] == 1)
{
cnt++;
}
if (cnt == l)
{
if (j + 1 <= n && a[j + 1] != 1)
{
a[j] = 0;
a[j + 1] = 1;
}
}
}
}
for (int i = 1; i <= n; i++)
{
if (a[i] == 1)
{
cout << i << " ";
}
}
return 0;
}
abc257_c
题目翻译
有 $n$ 个人,每个人有个体重 $w_i$,以及 $\tt{0}$ 代表他是小孩,$\tt{1}$ 代表成人。
我们认为,比 $X$ 轻的是小孩,反之是成人。
请选择一个 $X$,使身份匹配正确的人数最多。
题目思路
把这些人按体重排序,相同体重成人在前。
统计这里一共多少成人。
对于每个 $[1,i]$ 的区间,算一下类似前缀和的操作。
是小孩,之前统计的加 $1$,反之 $-1$。
AC 代码
struct node
{
bool f;
int w;
} a[200005];
bool cmp (node x, node y)
{
if (x.w == y.w)
{
return x.f > y.f;
}
return x.w < y.w;
}
int main()
{
int n, ch = 0, ans;
cin >> n;
char c;
for (int i = 1; i <= n; i++)
{
cin >> c;
if (c == '0')
{
a[i].f = 0;
}
else
{
a[i].f = 1;
ch++;
}
}
for (int i = 1; i <= n; i++)
{
cin >> a[i].w;
}
sort (a + 1, a + n + 1, cmp);
ans = ch;
for (int i = 1; i <= n; i++)
{
if (a[i].f == 0)
{
ch++;
}
else
{
ch--;
}
ans = max (ans, ch);
}
cout << ans << endl;
return 0;
}
abc257_d
题目翻译
有 $n$ 个蹦床,每个蹦床坐标为 $(x_i,y_i)$,并拥有主场 buff $p_i$ 加持。
(这样说是不是通俗易懂
可以自选起点。
如果从第 $i$ 个往第 $j$ 个跳,所需 $S\times p_i\geq \left|x_i-x_j\right|+\left|y_i-y_j\right|$ 的必备条件。
问 $S$ 最小多少。
题目思路
Floyd 最短路。
先求出从 $i$ 跳到 $j$ 的所需 $S$,再用 Floyd 做最短路,看经过中间过渡,能否缩小 $S$。
转移即为 $f_{i,j} = \min(\max (f_{i,k}, f_{k,j}), f{i,j})$。
AC 代码
ll x[205], y[205], p[205];
ll f[205][205];
int main()
{
ll n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> x[i] >> y[i] >> p[i];
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
ll s = abs (x[i] - x[j]) + abs (y[i] - y[j]);
if(s%p[i]==0)f[i][j]=s/p[i];
else f[i][j]=s/p[i]+1;
}
}
for (int k = 1; k <= n; k++)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
f[i][j] = min (max (f[i][k], f[k][j]), f[i][j]);
}
}
}
ll ans = 1e20;
for (int i = 1; i <= n; i++)
{
ll x = -1e20;
for (int j = 1; j <= n; j++)
{
x = max (f[i][j], x);
}
ans = min (ans, x);
}
cout << ans << endl;
return 0;
}
abc257_e
题目翻译
有 $9$ 种数字,$1,2,\dots9$。
数字 $i$ 可以花 $c_i$ 的价格购买,你有 $n$ 元。
最后输出你购买的数字拼成的最大值。
题目思路
我们考虑,先让位数最大。
然后,再最大化最高位、次高位、次次高位,一直往下。
最大位数,即为用 $n$ 除以最便宜的价钱。
然后,你可能会有剩余的钱。
剩余的,我们开始置换。
从 $9$ 开始枚举,能换就换,并输出你置换的数字。
这样最大化了较高位,还保证位数没有变少。
具体可以品味下代码。
AC 代码
int c[20];
int main()
{
int n, mnc = INT_MAX, maxn;
cin >> n;
for (int i = 1; i <= 9; i++)
{
cin >> c[i];
if (c[i] <= mnc)
{
mnc = c[i];
maxn = i;
}
}
int cnt = n / mnc;
int x = 0, cnt2 = 0;
int s = n - cnt * mnc;
for (int i = 9; i >= 1; i--)
{
if (i > maxn)
{
if (c[i] - mnc <= s)
{
cnt2 = s / (c[i] - mnc);
cnt -= cnt2;
s%=c[i] - mnc;
for (int j = 1; j <= cnt2; j++)
{
cout << i;
}
}
}
}
for (int i = 1; i <= cnt; i++)
{
cout << maxn;
}
return 0;
}