预测难度
- Easy : C I K L
- Easy-medium : D E F J M
- Medium : G H
- Medium-hard : B
- Hard : A
实际情况
- Easy : C
- Easy-medium : I L
- Medium : K M
- Medium-hard : G H J
- Hard : A B D E F
题解
A - Come A Little Closer
题意
移动一个坐标,使能把所有坐标框起来的最小矩形面积最小。
思路
很明显,面积只与横纵轴方向上最远的 个点有关。所以对每个点进行移动,维护答案最小值即可。
核心代码
struct pt{ int x, y;};
struct axis{ int mn1, mn2, mx2, mx1;
axis(int a, int b) { mx1 = mn1 = a; mx2 = mn2 = b; update_max(); update_min(); }
void update_min() { if(mn1 > mn2) swap(mn1, mn2); }
void update_max() { if(mx2 > mx1) swap(mx2, mx1); }
void add(int n) { mx2 = max(mx2, n); mn2 = min(mn2, n); update_max(); update_min(); }
int seg(int n) { int mx = mx1, mn = mn1; if(n == mx) mx = mx2; if(n == mn) mn = mn2; return mx - mn + 1; }};
void solve(){ int n; cin >> n;
vector<pt> a(n); for(auto& [x, y] : a) cin >> x >> y;
if(n < 3) { cout << n << endl; return; }
axis xs(a[0].x, a[1].x), ys(a[0].y, a[1].y); for(int i = 2; i < n; i++) { xs.add(a[i].x); ys.add(a[i].y); }
int ans = xs.seg(-1) * ys.seg(-1);
for(int i = 0; i < n; i++) { int xseg = xs.seg(a[i].x), yseg = ys.seg(a[i].y); if(xseg * yseg == n - 1) ans = min(ans, min((xseg + 1) * yseg, xseg * (yseg + 1))); else ans = min(ans, xseg * yseg); }
cout << ans << endl;}B - Only One Step
题意
给出一个出发点 ,以及范围 。判断范围内有所少个点是可达的。
思路
不难得出,所有的正整数同属一个连通分量。因此,对于任意起点 和区间 ,区间内的所有节点均可达,答案即为 。
证明:
考虑恒等式
即
因此,对于任意 ,节点 与节点 和 相连。
由此可得:
-
节点 与 通过节点 相连;
-
对于任意 ,节点 与 通过节点 相连。
于是,所有正整数通过相邻整数的连接构成一个连通图。
核心代码
void solve(){ int s, l, r; cin >> s >> l >> r;
cout << r - l + 1 << endl;}C - Hello BlueBird
题意
输出 行带双引号的字符串。
思路
考察基本语法,注意逃逸字符。
核心代码
void solve(){ int n; cin >> n;
while(n--) cout << "\"Hello, BlueBird!\"" << endl;}D - 正弦函数的前n项泰勒展开
题意
按照以下公式算近似值:
思路
每次都从头开始算每一项未必太麻烦了。
从第二项开始,每一项都可以由前一项递推得出:
核心代码
void solve(){ double x; int n; cin >> x >> n;
double sum = 0.0, term = x;
for(int i = 0; i < n; i++) { sum += term; term = -term * x * x / ((2 * i + 2) * (2 * i + 3)); }
cout << sum << endl;}E - What The Dog Doing?(Easy Version)
题意
统计所有二进制位的出现频率,问多少个位满足第 位出现频率等于 次。
思路
很明显,所有的正整数都是可以写成二进制的形式的。那么就可以按照二进制逐位分解,而这个过程就是按照 的幂分解的。所以,所有的正整数都满足“刀盾数”的定义。
数据范围是 ,在 类型范围之内。
那么,我们对每个数,跑 位逐位统计频率,然后再遍历 到 统计答案就好了。
核心代码
void solve(){ int n; cin >> n;
vector<int> a(n); for(int& i : a) cin >> i;
vector<int> f(32); for(int& i : a) { int d = 0; while(i) { f[d++] += i & 1; i >>= 1; } }
int ans = 0; for(int i = 1; i < 32; i++) if(f[i] == i) ans++;
cout << ans << endl;}F - What The Dog Doing?(Hard Version)
题意
再添加任意一个正整数,使最终满足条件的数量尽可能更多。
思路
换句话来说,对于每一位,都有机会让其频率增加 。
那么如果某一位刚好还差 ,那么我们就可以加上。每个满足该条件的位都会让答案在原基础上 。
那么我们只需要把 题的 if(f[i] == i) 改成 if(f[i] == i || f[i] + 1 == i) 即可通过该题。
核心代码
void solve(){ int n; cin >> n;
vector<int> a(n); for(int& i : a) cin >> i;
vector<int> f(32); for(int& i : a) { int d = 0; while(i) { f[d++] += i & 1; i >>= 1; } }
int ans = 0; for(int i = 1; i < 32; i++) if(f[i] == i || f[i] + 1 == i) ans++;
cout << ans << endl;}G - 图灵的诅咒
题意
不断对数组进行赋值操作:
每一轮对每个元素执行
直到整个数组只剩下一种元素。
问操作会持续多少轮。
思路
经过观察,对数组进行排序之后,每个缺失的数字都会使操作多进行一轮。
核心代码
Solution 1
void solve(){ int n; cin >> n;
vector<int> a(n); for(int& i : a) cin >> i;
sort(a.begin(), a.end());
if(a[0] == a[n - 1]) cout << 0 << endl; else if (a[0] != 0) cout << -1 << endl; else { int ans = 1; for(int i = 1; i < n; i++) ans += max(a[i] - a[i - 1] - 1, 0LL); cout << ans << endl; }}Solution 2
void solve(){ int n; cin >> n;
vector<int> a(n); for(int& i : a) cin >> i;
set<int> s(a.begin(), a.end());
if(s.size() == 1) cout << 0 << endl; else if(!s.count(0)) cout << -1 << endl; else cout << *s.rbegin() + 2 - s.size() << endl;}H - 这题有教育意义
题意
字符串转柱状图。
思路
按题意模拟即可。
核心代码
void solve(){ int n; string s; cin >> n >> s;
vector<int> f('Z' + 1); int mx = 0; for(char& c : s) { f[c]++; mx = max(mx, f[c]); }
for(int i = mx; i > 0; i--) { for(char c = 'A'; c <= 'Z'; c++) if(f[c]) cout << (f[c] >= i ? '*' : ' '); cout << endl; }
for(char c = 'A'; c <= 'Z'; c++) if(f[c]) cout << c; cout << endl;}I - 听说牌子是可以合成的(
题意
求最多能拥有的金牌数。
思路
模拟即可。
核心代码
void solve(){ int Au, Ag, Cu, x, y; cin >> Au >> Ag >> Cu >> x >> y;
while(Cu >= x || Ag >= y) { Ag += Cu / x; Cu %= x;
Au += Ag / y; Cu += Ag / y; Ag %= y; }
cout << Au << endl;}J - MEX × MIN = const?
题意
求区间 。
思路
mex 和 min 之中必有一个为 。
所以,正如题目名字所言:
核心代码
void solve(){ int _, q; cin >> _ >> q;
while(q--) cout << 0 << endl;}K - Kill And Keep
题意
保持每个数位和不变,尽可能删掉更多的数位。
思路
删掉所有的 。
核心代码
Solution 1
void solve(){ int n; cin >> n;
vector<int> a(n); for(int i = 0; i < n; i++) cin >> a[i];
auto f = [](int x) -> int { int res = 0; while(x) { int d = x % 10; if(d) res = res * 10 + d; x /= 10; } return res; };
for(int i = 0; i < n; i++) a[i] = f(f(a[i]));
for(int i = 0; i < n; i++) cout << a[i] << " \n"[i == n - 1];}Solution 2
void solve(){ int n; cin >> n;
vector<string> a(n); for(int i = 0; i < n; i++) cin >> a[i];
for(int i = 0; i < n; i++) { string t = ""; for(char& c : a[i]) if(c != '0') t += c; a[i] = t; }
for(int i = 0; i < n; i++) cout << a[i] << " \n"[i == n - 1];}L - Reach The MAX(Easy Version)
题意
左右传递赋值,求数组最大和。
思路
容易想到,选最大值,左右扩散至整个数组。答案就是 。
核心代码
void solve(){ int n; cin >> n;
vector<int> a(n); for(int i = 0; i < n; i++) cin >> a[i];
cout << *max_element(a.begin(), a.end()) * n;}M - Reach The MAX(Hard Version)
题意
选定区间,然后把区间内的数字都变成两个端点中的较大值。
思路
不难发现,只有首位两个元素无法被操作影响。其他元素都可以通过一系列操作变成数组的最大值。所以答案就是 。
核心代码
void solve(){ int n; cin >> n;
vector<int> a(n); for(int i = 0; i < n; i++) cin >> a[i];
cout << a[0] + a[n - 1] + (n - 2) * *max_element(a.begin(), a.end()) << endl;}如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时



