- 月赛题解
【202605】月赛语法组题解
- @ 2026-5-19 16:33:12
A
- 50pts
使用循环模拟每次吃的情况,判断能否达到爆爽范围
-100pts
为吃的包数,即: 满足该不等式则输出 Yes,否则输出 No。
求出满足最低爆爽辣度要求的最小包数 :需要满足 ,对 做向上取整; 不超过辣度上限的最大包数 :需要满足 ,对 做向下取整。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
double low = 0.9 * n; // 爆爽下限
int up = n; // 爆爽上限
// 核心公式:计算最小包数(向上取整)、最大包数(向下取整)
int min_k = ceil(low / m);
int max_k = up / m;
cout << (min_k <= max_k ? "Yes" : "No") << endl;
return 0;
}
B
#include <bits/stdc++.h>
using namespace std;
int main()
{
int y; cin >> y;
int k = sqrt(y);
if (k * k != y) {
cout << "No";
return 0;
}
if (y % 400 == 0 || y % 4 == 0 && y % 100)
cout << "Yes";
else
cout << "No";
return 0;
}
C
#include <iostream>
#include <vector>
using namespace std;
bool ok(int x) {
if (x < 10) return 1;
int a = x % 10;
x /= 10;
while (x) {
int b = x % 10;
if ((a - b > 2) || (b - a > 2)) return 0;
a = b;
x /= 10;
}
return 1;
}
int main() {
int n, cnt = 0, num = 0;
cin >> n;
while (cnt < n) {
num++;
if (ok(num)) cnt++;
}
cout << num << endl;
return 0;
}
D
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t; cin >> t;
while (t--) {
int n; cin >> n;
long long sm = 0;
int cnt0 = 0, cnt1 = 0, cnt2 = 0; // 统计余0、1、2的元素数量
for (int i = 1; i <= n; ++i) {
int x; cin >> x;
sm += x;
int m = x % 3;
if (m == 0) cnt0++;
else if (m == 1) cnt1++;
else cnt2++;
}
int mod = sm % 3;
int ans = n;
if (mod == 0) ans = 0; // 总和已是3的倍数,无需删除
else if (mod == 1) {
// 方案1:删1个余1的元素;方案2:删2个余2的元素
if (cnt1 >= 1) ans = min(ans, 1);
else ans = min(ans, 2);
} else {
// 方案1:删1个余2的元素;方案2:删2个余1的元素
if (cnt2 >= 1) ans = min(ans, 1);
else ans = min(ans, 2);
}
cout << ans << endl;
}
return 0;
}
E
注意 ,也就是说修改某段的重复字母一定可以不影响更靠后的子段。
模拟题目要求的过程即可
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T = 1;
while (T--)
{
int N, K;
cin >> N >> K;
string s;
cin >> s;
int cnt[300] = {0};
int ans = 0;
for (int l = 0, r = 0; r <= N;)
{
if (r - l < K)
{
cnt[s[r]]++;
r++;
continue;
}
for (char c = 'a'; c <= 'z'; c++)
{
if (cnt[c] > 1)
{
int t = cnt[c] - 1;
ans += t;
for (int j = r - 1; j >= l; j--)
if (s[j] == c && t)
s[j] = ' ', t--;
cnt[c] = 1;
}
}
cnt[s[l]]--;
l++;
}
cout << ans << '\n';
}
return 0;
}
F
首先我们要求出最大得分是多少,也就是尽量删除尽可能多的 ,那么 靠前的数字就要大一些,因此我们不难想到最优情况实际上就是把 降序排列。
此时我们模拟一遍就会发现,对于 中的最小值 ,所有 中大于 的数字一定都会被删除,而反之小于 的数字是不可能被删除的。
因此最大的得分实际上就是 中大于 的数字个数。
此时我们考虑如何求方案数,也就是说还有哪些情况也能使得答案取到上述的个数。
那么再次模拟一遍,我们会发现实际上只需要把 中大于 的所有数字都放在开头的部分,而剩下的部分放在后面,即将 分成两段,第一段全是大于 的数,第二段全是小于 的。
我们发现此时必然也能取到答案,而如果不是这样的情况,则必然取不到,因为会把 删掉,导致后面的 更难被删除。
因此前一段随意排列,后一段随意排列,答案就是两段长度的阶乘之积。(乘法原理)
#include <bits/stdc++.h>
using namespace std;
int MOD = 1e9 + 7;
int main()
{
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
int mn = 2e9;
for (int i = 1, x; i <= n; i++)
{
cin >> x;
mn = min(mn, x);
}
int x = 0, y = 0;
for (int i = 1; i <= n; i++)
{
if (a[i] > mn)
{
x++;
}
else
{
y++;
}
}
long long ans = 1;
for (int i = 1; i <= x; i++)
{
ans = (ans * i) % MOD;
}
for (int i = 1; i <= y; i++)
{
ans = (ans * i) % MOD;
}
cout << ans << endl;
return 0;
}
0 条评论
目前还没有评论...