A. Letter Song ~ 致十年后的我们
题意
已知你在 Y 年 M 月 D 日向十年后的自己发送了一条消息;请你精确的计算出,哪一天的自己会收到这条消息。
大概思路
不难,直接字符串截取前四个,转int后加10,直接输出,并顺便输出后半部分。
参考代码
void solve() {
std::string s;
std::cin >> s;
int y = std::stoi(s.substr(0, 4));
std::cout << y + 10 << s.substr(4);
}
B. 简单图形问题 - 0123
题意
对于给定的未知多边形的面积,请你判断这是一个以整数为边长的正方形、或是以整数为边长的等边三角形、或是两者均是、或是两者均不是。
大概思路
简单数学题,易知等边三角形面积一定会挂个无理数 $\sqrt 3$,所以只需要判断输入是否为平方数即可。
参考代码
void solve() {
int n;
std::cin >> n;
int n_ = std::sqrt(n);
if (n_ * n_ == n) {
std::cout << 0 << "\n";
} else {
std::cout << 3 << "\n";
}
}
C. 小红的机器人构造 - Ⅰ+Ⅱ+Ⅲ
题意
在无限大的网格平面上,我们使用 $(x,y)$ 表示网格中第 $x$ 行第 $y$ 列的单元格。 小红有一只笨笨机器人初始位于 $(0,0)$ 单元格,她会向机器人下达 $n$ 个指令,机器人跟随指令上下左右移动。指令字符串由 $U,D,L,R$ 四个字符混合构成,以 $1$ 作为初始下标,形式化写作 $s1s2⋯sn$ 。具体的,假设 $t$ 时刻机器人位于 $(i,j)$ 单元格,若指令字符串的第 $t+1$ 个字符存在:
- 若 $s_{t+1}=U$ ,则第 $t+1$ 时刻机器人位于 $(i+1,j)$ ;
- 若 $s_{t+1}=D$ ,则第 $t+1$ 时刻机器人位于 $(i−1,j)$ ;
- 若 $s_{t+1}=L$ ,则第 $t+1$ 时刻机器人位于 $(i,j−1)$ ;
- 若 $s_{t+1}=R$ ,则第 $t+1$ 时刻机器人位于 $(i,j+1)$ ;
给出指令字符串,询问,能否删除部分指令(保持其余指令的相对位置不变),使得机器人最终位于 $(x,y)$ 。如果可以,计算有多少种不同的删除方案(删除不同下标视为不同方案),并输出其中任意一种。
大概思路
什么OI制三合一?
对于task1,我们直接统计每种字符的数量,然后判断x,y方向对应的字符是否都分别大于等于 $|x|$ 和 $|y|$。
对于task2,我们可以在根据 $x$ 和 $y$ 的值,设定每种字符只能输出多少个,然后遍历字符串模拟即可。
对于task3,我们考虑基于最少输出字符的情况,一对一对的加上相反方向的字符,对最终位置不影响。然后枚举可以加多少对,用组合数算贡献即可。显然这个枚举是 $O(n)$ 的。
参考代码
constexpr int M = 1e9 + 7;
constexpr int N = 1e5 + 5;
i64 powp(i64 a, i64 n) {
i64 ans = 1;
while (n) {
if (n & 1) (ans *= a) %= M;
(a *= a) %= M;
n >>= 1;
}
return ans;
}
i64 inv(i64 x) {
return powp(x, M - 2);
}
i64 fac[N], invfac[N];
void pre() {
fac[0] = invfac[0] = 1;
for (int i = 1; i < N; i++) fac[i] = fac[i-1] * i % M;
invfac[N - 1] = inv(fac[N - 1]);
for (int i = N - 2; i >= 1; i--) invfac[i] = invfac[i + 1] * (i + 1) % M;
}
i64 C(i64 n,i64 m) {
if (m > n) return 0;
return fac[n] * invfac[n - m] % M * invfac[m] % M;
}
void solve() {
int n, x, y;
std::cin >> n >> y >> x;
std::string s;
std::cin >> s;
std::map<char, int> cnt;
for (auto &c : s) cnt[c]++;
//task1
bool ck = ((x > 0 ? (cnt['R'] >= x) : (cnt['L'] >= -x)) & (y > 0 ? (cnt['U'] >= y) : (cnt['D'] >= -y)));
if (ck) {
std::cout << "YES ";
//task2
auto cnt_ = cnt;
if (x > 0) {
cnt_['L'] = 0;
cnt_['R'] = x;
} else {
cnt_['R'] = 0;
cnt_['L'] = -x;
}
if (y > 0) {
cnt_['D'] = 0;
cnt_['U'] = y;
} else {
cnt_['U'] = 0;
cnt_['D'] = -y;
}
auto cnt__ = cnt_;
for (auto &c : s) {
if (cnt_[c]) {
std::cout << c;
cnt_[c]--;
}
}
std::cout << " ";
//task3
i64 ans = 1;
if (x >= 0) {
i64 tmp = 0;
for (int i = 0; i <= std::min(cnt['L'], cnt['R'] - cnt__['R']); i++) {
(tmp += C(cnt['R'], cnt__['R'] + i) * C(cnt['L'], i) % M) %= M;
}
(ans *= tmp) %= M;
} else {
i64 tmp = 0;
for (int i = 0; i <= std::min(cnt['R'], cnt['L'] - cnt__['L']); i++) {
(tmp += C(cnt['L'], cnt__['L'] + i) * C(cnt['R'], i) % M) %= M;
}
(ans *= tmp) %= M;
}
if (y >= 0) {
i64 tmp = 0;
for (int i = 0; i <= std::min(cnt['D'], cnt['U'] - cnt__['U']); i++) {
(tmp += C(cnt['U'], cnt__['U'] + i) * C(cnt['D'], i) % M) %= M;
}
(ans *= tmp) %= M;
} else {
i64 tmp = 0;
for (int i = 0; i <= std::min(cnt['U'], cnt['D'] - cnt__['D']); i++) {
(tmp += C(cnt['D'], cnt__['D'] + i) * C(cnt['U'], i) % M) %= M;
}
(ans *= tmp) %= M;
}
std::cout << ans;
std::cout << "\n";
} else {
std::cout << "NO\n";
}
}
D. 小红的差值构造 - easy+hard+extreme
题意
小红有一个长度为 $n$ 的数组 $\{1,2,…,n\}$ 和一个整数 $l$ ,她想找到这样两个整数 $x$ 和 $y$ ,满足 $y−x=l$,记 $f_i=\min{∣a_i−x∣,∣a_i−y∣}$,使得 $f_1+f_2+⋯+f_n$ 最小。
你需要输出满足条件的 $x$ 和 $y$ ,以及这个最小值。
大概思路
分类讨论,当 $l > n$ 时,显然我们无法将 $x$ 和 $y$ 同时置于数组的值域中,因此我们可以选择将其中一个端点居中放置到数组中,容易证明,这样的贡献算出来一定是最小的。设该贡献为 $calc(n)$,表示对长为 $n$ 的区间,当 $l > n$ 时的最优答案,我们可以直接用两个等差数列求和搞定该值的计算。
当 $l <= n$ 时,我们也要尽可能“居中”地放 $x$ 和 $y$。手画样例可知,答案可以划分成两个 “$l > n$” 的情况,分别长为 $l$ 和 $n - l$。此时答案即为 $calc(l) + calc(n - l)$
参考代码
void solve() {
i64 n, l;
std::cin >> n >> l;
auto calc = [](i64 n) {
i64 n_ = n / 2;
return 1ll * (1ll + n_) * n_ - (n % 2 == 0 ? n_ : 0);
};
if (l <= n) {
i64 l_ = (l + 1) / 2;
i64 r = n / 2 + l_ + (l % 2 == 0);
std::cout << r - l << " " << r << " ";
std::cout << calc(n - l) + calc(l);
} else {
i64 l_ = (n + 1) / 2;
std::cout << l_ - l << " " << l_ << " ";
std::cout << calc(n);
}
std::cout << "\n";
}
吐槽
这个D题,我真的是无语si了,怎么交都是错的,然后快结束的时候,你跟我说数据有问题,会重测? 重测后赛时跟我说赛时第一发就是AC(忽略那个TLE,我忘删vectora(n)了)?那我整整一个1小时在对空气debug是吗?