语法周赛 Round 26 题解
2024年12月25日大约 3 分钟
A. 等差数列变化求和
分析
- 难度:比较麻烦的数学题。
- 子任务 1(30 分):
min(r, max(l, a1))
。 - 子任务 2(30 分):直接暴力枚举即可。
- 子任务 3(40 分):显然麻烦的点是情况非常多,可能递增或递减,可能分为三段、两段或一段,中间的情况也会非常复杂。 大家要学会不要只一味的判断当前情况,而要提前预处理做一些整理才能让后续事半功倍。我的代码第一步就是先把递减的序列转换为对应等价的递增序列。这样情况就简单了非常多。 然后把三段直接用数学方法算出分界点,分别用对应的规则进行计算即可。
满分参考代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, a1, d, l, r;
signed main()
{
freopen("sum.in", "r", stdin);
freopen("sum.out", "w", stdout);
cin >> n >> a1 >> d >> l >> r;
// 调整数列,为连续上升
if (d < 0)
{
a1 = a1 + (n - 1) * d;
d = -d;
}
int ans = 0;
// lllll
if (a1 < l)
{
// 前 cnt 项都 <= l,第 cnt+1 项肯定大于 l
int cnt = (l - a1) / d + 1;
if (cnt > n)
cnt = n;
ans += cnt * l; // cnt 个 l
a1 += cnt * d; // 首项变到第 cnt+1 项
n -= cnt; // 现在少了 cnt 项
}
// 等差阶段
if (a1 < r)
{
// 前 cnt 项都 <= r,第 cnt+1 项肯定大于 r
int cnt = (r - a1) / d + 1;
if (cnt > n)
cnt = n;
// 首项 加 末项 乘以 项数 除以 2
ans += (a1 + (a1 + (cnt - 1) * d)) * cnt / 2;
a1 += cnt * d;
n -= cnt;
}
// rrrrrr 后面的全都大于 r
ans += n * r;
cout << ans;
return 0;
}
B. 停车费计算
分析
- 难度:基础的求和,求和的每一项都根据具体情况计算价格即可。
- 子任务 1(30 分):每天只有两种费用,
或 元,判断每天停车时间是否大于 来决定加多少即可。 - 子任务 2(30 分):第一个小时和后续价格一致,超过
元直接算出多少个小时乘以对应的单价即可。 - 子任务 3(40 分):每天的停车时长算出属于哪一档,按规则计算即可。
满分参考代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n; // 总次数
int x; // 免费时长
int y, a, b; // 第一个 y 分钟 a 元。后面每 y 分钟 b 元
int t[10000 + 5], ans;
signed main()
{
freopen("park.in", "r", stdin);
freopen("park.out", "w", stdout);
cin >> n;
cin >> x;
cin >> y >> a >> b;
for (int i = 1; i <= n; i++)
cin >> t[i];
ans = 0;
for (int i = 1; i <= n; i++)
{
if (t[i] <= x)
continue;
if (t[i] <= y)
{
ans += a;
continue;
}
int cnt = (t[i] + (y - 1)) / y;
ans += a + (cnt - 1) * b;
}
cout << ans;
return 0;
}
C. 复制画作
分析
- 难度:基础绘图,注意转义符。
满分参考代码
#include <bits/stdc++.h>
using namespace std;
string g[4] = {"./\\.", "/..\\", "\\../", ".\\/."};
int main()
{
freopen("copy.in", "r", stdin);
freopen("copy.out", "w", stdout);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int row = 0; row <= 3; row++)
{
for (int j = 1; j <= m; j++)
{
cout << g[row];
}
cout << "\n";
}
return 0;
}
D. 计算补码
分析
- 难度:按照补码规则处理即可,最后的加
稍微麻烦一点。按竖式计算即可。
满分参考代码
#include <bits/stdc++.h>
using namespace std;
string s;
int main()
{
freopen("code.in", "r", stdin);
freopen("code.out", "w", stdout);
cin >> s;
if (s[0] == '0')
{
cout << s;
return 0;
}
for (int i = 1; i <= (int)s.size() - 1; i++)
{
if (s[i] == '0')
s[i] = '1';
else
s[i] = '0';
}
int add = 1; // 进位
for (int i = (int)s.size() - 1; i >= 0; i--)
{
int num = s[i] - '0' + add;
add = num / 2;
num = num % 2;
s[i] = '0' + num;
}
cout << s;
return 0;
}