995 字
5 分钟
2026 ccpc南昌邀请赛
NOTE

比赛链接:Unofficial Mirror 2026 CCPC National Invitational (Nanchang) and The 3rd Jiangxi Provincial Programming Contest

D - 电梯#

关键词:思维,数学

题目要求:每部电梯必须停在第 11 层和第 nn 层;对于任意两层 x,yx,y,需要存在一部电梯,使得 x,yx,y 是这部电梯的相邻停靠层,也就是可以直达。输出时需要给出最少电梯数,并构造每部电梯的停靠序列,且总停靠层数不能超过 2×1062 \times 10^6

思路#

考虑如何转化问题,假设现在有 nn 层楼,如果一部电梯停靠 1,3,5,n1,3,5,n,那么它可以直达的楼层对是 (1,3),(3,5),(5,n)(1,3),(3,5),(5,n),也就是说一部电梯的停靠方案,本质上是把整段楼层分割成若干区间。例如 1,3,5,81, 3, 5, 8 对应区间 [1,3],[3,5],[5,8][1, 3], [3, 5], [5, 8]

所以题目变成:用最少的区间划分方案,覆盖所有楼层对 (x,y)(x, y)

G - 可能是字符串签到题#

关键词:贪心,前缀和

思路#

询问某个区间内出现次数最多的子串的个数,实际上由于长度为 11 的子串也是合法子串,且任何长度大于 11 的子串,出现次数都不可能超过它首字符的出现次数,所以求的就是某个区间内出现次数最多的字母的数量,使用前缀和预处理,每次询问枚举 2626 个字母,更新答案即可。

证明:假设在 s[l,r]s[l,r] 中,某个子串 TT 出现了 kk 次。

例如:

T=abT = \texttt{ab}

如果 ab\texttt{ab} 出现了 kk 次,那么每一次 ab\texttt{ab} 的出现位置上,开头字符 a\texttt{a} 也一定出现了一次。

所以:

cnt(ab)cnt(a)\operatorname{cnt}(\texttt{ab}) \le \operatorname{cnt}(\texttt{a})

更一般地,假设子串 TT 的第一个字符是 cc,那么:

cnt(T)cnt(c)\operatorname{cnt}(T) \le \operatorname{cnt}(c)

Code#

// Problem: CF GYM 106554 G
// Contest: Codeforces - [Unofficial Mirror] 2026 CCPC National Invitational (Nanchang) and The 3rd Jiangxi Provincial
// Programming Contest URL: https://codeforces.com/gym/106554/problem/G
// Time: 2026-05-28 22:22:17
#include <bits/stdc++.h>
using namespace std;
// clang-format off
#define endl '\n'
#define all(x) (x).begin(), (x).end()
#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// clang-format on
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pdd = pair<double, double>;
using pll = pair<long long, long long>;
using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};
const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10;
int cnt[N][26];
void solve()
{
int n, q;
cin >> n >> q;
string s;
cin >> s;
s = " " + s;
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < 26; j++)
cnt[i][j] = cnt[i - 1][j];
cnt[i][s[i] - 'a']++;
}
while (q--)
{
int l, r;
cin >> l >> r;
int res = 0;
for (int i = 0; i < 26; i++)
res = max(res, cnt[r][i] - cnt[l - 1][i]);
cout << res << endl;
}
}
int main()
{
fastio();
int T = 1;
// cin >> T;
while (T--)
solve();
return 0;
}

L - 三人成角#

关键词:思维

思路#

题目是:在 NN 个等距圆周点中选 33 个点,问有多少种选法构成直角三角形;且选法只看最终选中的 33 把椅子,不区分人坐哪一把。

注意到直径所对的圆周角为 9090 度, 分奇偶考虑。

nn 为偶数的时候,每个点都有一个正对点,对于每一条直径,第三个点从剩下的 n2n-2 个点中任选,答案为 n(n2)2\frac {n(n-2)}{2}

而奇数点时,圆周上不存在正对着的两把椅子,答案为 00

Code#

// Problem: CF GYM 106554 L
// Contest: Codeforces - [Unofficial Mirror] 2026 CCPC National Invitational (Nanchang) and The 3rd Jiangxi Provincial
// Programming Contest URL: https://codeforces.com/gym/106554/problem/L Time: 2026-05-29 18:44:32
#include <bits/stdc++.h>
using namespace std;
// clang-format off
#define endl '\n'
#define all(x) (x).begin(), (x).end()
#define fastio() ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// clang-format on
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pdd = pair<double, double>;
using pll = pair<long long, long long>;
using i128 = __int128;
const int dx[] = {-1, 0, 1, 0, -1, 1, 1, -1};
const int dy[] = {0, 1, 0, -1, 1, 1, -1, -1};
const int inf = 0x3f3f3f3f;
const int N = 0;
void solve()
{
ll n;
cin >> n;
ll res = (n % 2 == 1 ? 0 : n * (n - 2) / 2);
cout << res << endl;
}
int main()
{
fastio();
int T = 1;
cin >> T;
while (T--)
solve();
return 0;
}