A - Long Loong
输入一个正整数 n n n,输出一个字符串:‘L’ + n n n 个 ‘o’ + ‘n’ + ‘g’。
解:
#include <bits/stdc++.h>
using namespace std;
int main() {
long long a;
cin >> a;
printf("L");
for (int i = 0; i < a; i++)
printf("o");
printf("ng\n");
return 0;
}
B - CTZ
输入一个数正整数 n n n, 输出这个数的二进制表示中有多少个后缀 ‘0’。
解:
#include <bits/stdc++.h>
using namespace std;
int main() {
long long a;
cin >> a;
long long ans = 0;
while (a) {
if (a % 2 == 0) {
ans++;
a /= 2;
}
else break;
}
printf("%lld\n", ans);
return 0;
}
C - Even Digits
输入一个正整数 n n n,输出在(0,2,4,6,8,20,22,24,26,28,40,…)进制下第 n n n 个数是多少。从 0 0 0 开始计数。
解:
只需将 0, 1, 2, 3, 4替换成 0, 2, 4, 6, 8。
#include <bits/stdc++.h>
using namespace std;
int q[100], idx;
int main() {
long long a;
cin >> a;
a--;//从0开始计数,所以先减去1
long long ans = 0;
if (!a) printf("0");// 再特判
while (a) {
q[++idx] = (a % 5) * 2;
a /= 5;
}
for (int i = idx; i >= 1; i--)
printf("%d", q[i]);
return 0;
}
D - Pyramid
输入一个正整数数
n
n
n 和
n
n
n 个正整数,只能进行以下两种操作,操作次数不限:
1、 删除第一个数或者删除最后一个数。
2、 将一个位置的数减 1。
问能构成的最高的金字塔型有多高。
金字塔型即:1、1 2 1、1 2 3 2 1、1 2 3 4 3 2 1,高度分别是 1,2,3,4。
解:
动态规划的思想,先考虑左半部分,假设循环枚举到第 i i i 个位置,如果前面一个位置能达到的高度为 m m m,则当前位置能达到的最高高度为 m i n ( a [ i ] , m + 1 ) min(a[i], m + 1) min(a[i],m+1)。因为:
1、如果前面一个位置能达到的最高高度大于第 i i i 个位置的数 a [ i ] a[i] a[i],那么当前最大高度只能达到 a [ i ] a[i] a[i] 。因为只减不加,所以最大高度为 a [ i ] a[i] a[i];再者可以通过将前面的数全部减 1 1 1 使得前面的数减小到 a[i] - 1,使得 a [ i ] a[i] a[i] 这个高度能达到。
2、如果当前位置比前面一个位置能达到的最高高度大,由于要维持金字塔型,前面的最大高度为
m
m
m,所以只能将当前的数变为
m
+
1
m+1
m+1 来达到最大高度。
综上即是
m
i
n
(
a
[
i
]
,
m
+
1
)
min(a[i], m + 1)
min(a[i],m+1) 的由来。
同理再考虑金字塔的右半部分,可得出第
i
i
i 个位置左半部分和右半部分能达到的最大高度,设为
l
[
i
]
,
r
[
i
]
l[i], r[i]
l[i],r[i],则以当前第
i
i
i 个位置为塔尖的金字塔最大高度为
m
i
n
(
l
[
i
]
,
r
[
i
]
)
min(l[i], r[i])
min(l[i],r[i])。枚举每一个位置作为塔尖,即可得出答案。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N], n;
int l[N], r[N];
int ans;
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
l[i] = min(a[i], l[i-1] + 1);
for (int i = n; i >= 1; i--)
r[i] = min(a[i], r[i+1] + 1);
for (int i = 1; i <= n; i++)
ans = max(ans, min(l[i], r[i]));
printf("%d\n", ans);
return 0;
}
拓展:
可以为题目进行拓展,比如将操作 1 1 1 改成可以删除任一位置的数;达到最大高度的同时将操作数降到最少。
//修改操作 1
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N], n;
int l[N], r[N];
int q[N], tt;
int ans;
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) {
while (tt && a[q[tt]] >= a[i]) tt--;
if (tt) l[i] = l[q[tt]] + min(i - q[tt], a[i] - a[q[tt]]);
else l[i] = min(a[i], i);
q[++tt] = i;
}
tt = 0;
for (int i = n; i >= 1; i--) {
while (tt && a[q[tt]] >= a[i]) tt--;
if (tt) r[i] = r[q[tt]] + min(q[tt] - i, a[i] - a[q[tt]]);
else r[i] = min(a[i], n - i + 1);
q[++tt] = i;
}
for (int i = 1; i <= n; i++)
ans = max(ans, min(l[i], r[i]));
printf("%d\n", ans);
return 0;
}