26牛客暑假多校7
点击查看题面
K题 D-Mail Institution Codes
题目大意
给定
为了消除相同缩写带来的冲突,程序按轮次进行动态调整:
- 每轮检查所有尚未获得唯一缩写的机构。
- 尚未唯一的机构会同时更新缩写:第
次调整会将名称中的第 个单词完整写出,后续单词仍保持首字母形式。 - 调整后,重新检查所有未锁定机构的缩写。若某个机构的缩写在所有机构中唯一,则该机构的缩写被永久锁定,后续不再更改。
- 重复上述过程,直到所有机构均获得唯一缩写。
需要按输入顺序输出最终每个机构的缩写。
数据范围:
- 每个机构名称由
个单词组成,单词间以单个空格分隔。 - 每个单词由
个英文字母组成(首字母大写,其余小写)。 - 输入保证所有机构的完整名称两两不同。
思路
由于数据规模非常小(
- 结构化存储:使用结构体
st维护机构信息:
s:按顺序保存该机构的所有单词。suo:布尔值,表示当前缩写是否已唯一并锁定。k:整数,表示当前已完整展开的单词数量。cur:当前轮次生成的缩写字符串。
- 缩写构建机制(
build方法):
- 遍历单词列表
,若单词下标 ,将整个单词 追加到 cur中;否则仅追加首字母。
- 模拟轮次循环:
- Step 1:对于所有未锁定的机构(
!suo),调用build()更新其cur字符串。 - Step 2:使用
std::map<string, int> cnt统计所有机构(包括已锁定与未锁定)当前cur的出现频次。 - Step 3:再次遍历,若某个未锁定机构的
cnt[a[i].cur] == 1,说明其缩写已无冲突,将其suo置为true。 - Step 4:统计剩余未锁定机构的数量。若数量为
,终止循环;否则对所有仍未锁定的机构执行 k++,进入下一轮。
复杂度分析
时间复杂度: 设机构数量为
- 单次构建缩写字符串的时间复杂度为
。 - 每一轮统计频次并更新状态的时间复杂度为
。 - 最多进行
轮调整即可确保所有名称两两不同(因为完整名称两两不同)。 - 总体时间复杂度为
。代入数据上限 次基础运算,运行时间在 毫秒以内,远远低于 秒的时间限制。
空间复杂度: 主要空间消耗在于存储单词列表与 map 映射。
- 存储所有机构单词需
空间。 - Map 存储中间字符串需
空间。 - 总体空间复杂度为
,占用空间不足 ,满足 的限制。
参考代码
参考代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct st {
std::vector<std::string> s;
bool suo = false;
int k = 0;
std::string cur;
void build() {
cur = "";
for (int i = 0; i < s.size(); i++) {
if (i < k) {
cur += s[i];
} else {
cur += s[i][0];
}
}
}
};
void fc() {
int n;
std::cin >> n;
std::vector<st> a(n);
std::cin.ignore();
std::string s;
for (int i = 0; i < n; i++) {
std::getline(std::cin, s);
std::stringstream ss(s);
std::string word;
while (ss >> word) {
a[i].s.push_back(word);
}
}
while (1) {
std::map<std::string, int> cnt;
for (int i = 0; i < n; i++) {
if (!a[i].suo) a[i].build();
cnt[a[i].cur]++;
}
int cn = 0;
for (int i = 0; i < n; i++) {
if (!a[i].suo && cnt[a[i].cur] == 1) {
a[i].suo = true;
}
if (!a[i].suo) cn++;
}
if (cn == 0) break;
for (int i = 0; i < n; i++) {
if (!a[i].suo) a[i].k++;
}
}
for (int i = 0; i < n; i++) {
std::cout << a[i].cur << "\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
while (t--) fc();
return 0;
}L题 Bobo's Lucky Modulo
题目大意
给定一个正整数
数据范围:
思路
1. 原理与变形
推导
设
将
针对余数与商的关系进行分类讨论:
- 情况一 (
):此时 ,直接可得 。 代入原方程: 。因为 ,商必须满足 ,故该情况下无合法解。 - 情况二 (
):此时 ,说明 除以 的实际商小于 。 设 除以 的商为 ( ),余数为 ( )。 代入展开式:
令
2. 解的周期分布与下界推导
将
由于
定义周期长度
取
根据题目限制
3. 统计解的算法步骤
遍历
- 定义周期:设
。 - 计算首个周期 (
):合法区间为 ,贡献解的个数为 。 - 计算后续周期 (
):令剩余数值区间长度为 :
- 包含
个完整周期,每个完整周期贡献 个合法解; - 剩余不完整周期长度为
,若 ,则额外贡献 个合法解。
复杂度分析
时间复杂度:
空间复杂度:
参考代码...
参考代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void fc() {
ll n;
std::cin >> n;
ll ans = 0;
// 枚举 b (代码中用 i 表示),根据 a_min = b^2 <= n,i 的上限为 sqrt(n)
for (ll i = 1; i * i <= n; i++) {
ll d = i * (i + 1); // 周期长度 d = b * (b + 1)
// 1. 处理第一个周期 (k = 1) 中的合法区间 [i^2, d - 1]
ll m = std::min(n, d - 1);
ans += std::max(0LL, m - i * i + 1);
// 2. 处理后续周期 (k >= 2)
ll k = n - m; // 剩余未统计的数值长度
// 每个完整周期 d 中包含 i 个合法解
ans += k / d * i;
// 处理最后一个不完整周期
ll c = k - k / d * d;
// 如果余下长度 c 超过了非合法前缀 i^2,则加上超出的合法部分
ans += std::max(0LL, c - i * i);
}
std::cout << ans << "\n";
}
int main() {
// 优化输入输出效率
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
// std::cin >> t;
while (t--) fc();
return 0;
}G题 Both of You, Dance Like You Want to Win!
题目大意
有
每轮 MAGI 选择两个尚未使用的模块
给出。 操作员必须立即将其中一个安装到初号机(左侧),另一个安装到二号机(右侧),且安装后不可更改。
问操作员是否存在一种确定性策略,使得无论 MAGI 如何自适应选择,最终两台 EVA 安装的模块数值之和完全相等。
数据范围:
且 为偶数 保证序列中每个数值的出现次数均为偶数
思路
1. 原理与分类讨论
本题的核心在于全信息在线零和博弈下的确定性策略构造。对于包含偶数个元素且每种数值均出现偶数次的序列,我们需要判断玩家(操作员)能否对对手(MAGI)自适应给出的任意点对进行左右定侧,使最终两侧元素之和严格相等。
通过对数值种类数
(1) 不同数值种类 的必胜构造策略
:所有元素数值相同,对手每轮给出的必定是同值对 ,直接将其分别放入左右两侧,两侧差值始终为 。 (数值为 ): 若对手给出同值对
或 ,直接左右平分; 若对手给出异值对
,采用交替定向策略:第 次按 放置,第 次按 放置。 由于
的总出现次数均为偶数,异值对 的总数量必然为偶数。因此交替定向后两两抵消,最终总差值为 。 (数值为 ): 对
、 、 三种异值对分别独立进行交替定向。 若某类异值对出现偶数次,则该类异值对完全抵消;
若三类异值对均剩下
对未配对,只需将这最后的 对分别定向为 、 与 (形成一个三元代数环)。其对两侧差值的贡献为:
因此总差值依然能完美抵消为
(2) 不同数值种类 的必败证明
当至少存在
设其中最小的
个互不相同的数值为 ,且每种数值至少有 个。 第一阶段:对手前两轮先后给出
和 。 玩家不论如何放置,假设最终左侧放置了 ,右侧放置了 (其中 分别为 的某种排列)。 第二阶段:对手利用剩余的第二份元素,将它们重新配对为
与 给出。 无论玩家在第二阶段如何定向,两侧总差值的绝对值均满足:
其中
2. 算法具体步骤
根据上述原理,本题无需模拟博弈全过程,只需对输入数据进行离散化统计:
使用
std::map或std::unordered_map统计序列中出现的不同数值种类数。 若
,说明可以通过交替定向与环形构造策略保证平衡,输出 YES;若
,对手可以通过四元素联动构造必败态,输出 NO。
复杂度分析
时间复杂度:std::map 进行频次统计,耗时为 std::unordered_map 可优化至
空间复杂度:
参考代码
参考代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void fc() {
int n;
std::cin >> n;
std::vector<int> a(n);
std::map<int, int> cnt;
for (int i = 0; i < n; i++) {
std::cin >> a[i];
++cnt[a[i]]; // 统计每种数值的出现次数
}
// 根据博弈充要条件:不同数值种类数 <= 3 时必胜,否则必败
std::cout << (cnt.size() <= 3 ? "YES" : "NO") << "\n";
}
int main() {
// 优化标准输入输出流性能
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
// std::cin >> t;
while (t--) fc();
return 0;
}