神犇博客友链

本文精选了三位编程高手的个人博客,这些博客不仅提供了高质量的题目和题解,而且页面简洁、代码风格优良,适合(准)程序员阅读。博主们还会不定期分享C++黑科技等内容。

1.神犇stone2000“英俊潇洒威武帅气牛逼哄哄智商爆表的伟大领袖szy”的博客,配合各大OJ(poj、洛谷等)食用效果更佳~

http://stone906229046.blog.163.com/

2.神犇cgk的blog,题目质量、题解质量可靠,页面简洁无广告,画风严谨有个性,代码风格适合(准)程序员,变量名通俗易懂,更有C++黑科技不定期放送,你,值得拥有:

http://chenguokai.16mb.com/

3.神犇fjj的blog,P党福利,一切尽在不言中……

http://www.cnblogs.com/fengjunjie/


基于数据驱动的 Koopman 算子的递归经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的Koopman算子的递归经网络模型线性化”展开,旨在研究纳米定位系统的预测控制问题,并提供完整的Matlab代码实现。文章结合数据驱动方法与Koopman算子理论,利用递归经网络(RNN)对非线性系统进行建模与线性化处理,从而提升纳米级定位系统的精度与动态响应性能。该方法通过提取系统隐含动态特征,构建近似线性模型,便于后续模型预测控制(MPC)的设计与优化,适用于高精度自动化控制场景。文中还展示了相关实验验证与仿真结果,证明了该方法的有效性和先进性。; 适合人群:具备一定控制理论基础和Matlab编程能力,从事精密控制、智能制造、自动化或相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于纳米级精密定位系统(如原子力显微镜、半导体制造设备)中的高性能控制设计;②为非线性系统建模与线性化提供一种结合深度学习与现代控制理论的新思路;③帮助读者掌握Koopman算子、RNN建模与模型预测控制的综合应用。; 阅读建议:建议读者结合提供的Matlab代码逐段理解算法实现流程,重点关注数据预处理、RNN结构设计、Koopman观测矩阵构建及MPC控制器集成等关键环节,并可通过更换实际系统数据进行迁移验证,深化对方法泛化能力的理解。
首页 题库 训练 比赛 作业 讨论 评测记录 排名 算法基础 2032kehaochen G. 【模拟试题】正确答案 G 传统题 1000ms 256MiB 问题描述 小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案。 “吔,我的答案和你都不一样!”,小Y说道,”我们去找犇们问答案吧”。 外卡组试卷中共有m道判断题,小H与小Y一共从其他n个犇那问了答案。之后又从小G那里得知,这n个犇中有p个考了满分,q个考了零分,其他犇不为满分或零分。这可让小Y与小H犯了难。你能帮助他们还原出标准答案吗?如有多解则输出字典序最小的那个。无解输出-1。 输入格式 第一行四个整数n, m, p, q,意义如上描述。 接下来n行,每一行m个字符’N’或’Y’,表示这题这个犇的答案。 输出格式 仅一行,一个长度为m的字符串或是-1。 样例1 输入数据 1 2 2 2 0 YY YY 输出数据 1 YY 数据范围 对于 30%的数据,n <= 100; 对于 60%的数据,n <= 5000 , m <= 100; 对于 100%的数据,1 <= n <= 30000 , 1 <= m <= 500. 0 <= p , q 且 p + q <= n。 进入在线编程模式 (Alt+E) 递交 【G2032】模拟训练 已认领 查看作业 成绩表 我的最近递交记录 帮助 状态正在进行…题目8开始时间2025-10-28 0:00截止时间2025-11-5 23:59可延期24 小时 状态 评测队列 服务状态 开发 开源 支持 帮助 联系我们 关于 关于 隐私 服务条款 版权申诉 Language 兼容模式 主题 Worker 0, 13msPowered by Hydro v5.0.0-beta.9 Community
11-01
我们来逐步分析这个问题,并给出正确的 C++ 解法。 --- ### ✅ 问题解析 题目大意: - 有 `m` 道判断题,每道题的答案是 `'Y'` 或 `'N'`。 - 有 `n` 个“犇”给出了他们的答案(每人一个长度为 `m` 的字符串,由 `'Y'` 和 `'N'` 组成)。 - 已知这 `n` 个人中: - 有 `p` 个人得了 **满分**(即所有题都答对); - 有 `q` 个人得了 **零分**(即所有题都答错); - 其余的人既不是满分也不是零分。 - 我们要根据这些信息,**还原出唯一的标准答案**(即每道题的正确答案)。 - 如果有多个可能的标准答案,输出**字典序最小的**。 - 如果无解,输出 `-1`。 --- ### 🔍 解题思路 #### 关键观察: 假设某个犇的答案为 `ans[i]`,如果我们假设标准答案是 `res`,那么这个犇的得分就是: > `score = 与 res 相同的位置数` - 若该犇是满分,则 `score == m` - 若该犇是零分,则 `score == 0` - 否则 `0 < score < m` 我们的目标是找出一个候选答案 `res`(长度为 `m`),使得可以从中选出: - 恰好 `p` 个犇,其答案与 `res` 完全相同(满分) - 恰好 `q` 个犇,其答案与 `res` 完全相反(零分,即每一位都不一样) - 剩下的 `n - p - q` 个人既不完全相同也不完全相反 并且我们要在所有合法的 `res` 中选择**字典序最小的**。 --- ### 🚀 算法设计 由于 `m <= 500`,但 `n <= 30000`,不能枚举所有 $2^m$ 种答案。 但是注意:**标准答案必须和至少 p 个犇完全一致,且和至少 q 个犇完全相反。** 因此我们可以考虑:**枚举每一个犇的答案作为候选标准答案,或其取反作为候选标准答案**。 为什么? 因为如果某个犇是满分,那他的答案就是标准答案;如果是零分,那他的答案取反就是标准答案。 所以,真正的标准答案一定出现在以下集合中: > `{ ans[i], reverse(ans[i]) }` 对于所有 i ∈ [0, n) 其中 `reverse(s)` 表示将 `'Y'` 变 `'N'`,`'N'` 变 `'Y'` 这样最多只有 `2n` 个候选答案,而 `n <= 30000`,但我们只需要检查最多 `60000` 个候选?——不行,太多了。 但注意:我们只关心那些有可能成为标准答案的串。而且我们最终要的是字典序最小的合法答案。 优化思路: 我们可以遍历所有 `n` 个原始答案及其取反,生成最多 `2n` 个候选答案,然后去重后排序(按字典序),再逐个验证是否满足条件。 但由于 `n=30000`,最多 `60000` 个候选串,每个串长 `500`,总时间复杂度约为 `60000 * 30000 = 1.8e9`,可能会超时。 需要更高效的方法。 --- ### ✅ 更优策略 换一种角度思考: 设我们猜测某个字符串 `res` 是标准答案。 对于每个犇 `i` 的答案串 `s[i]`,我们可以计算它与 `res` 的匹配数: ```cpp int cnt = 0; for (j=0; j<m; j++) if (s[i][j] == res[j]) cnt++; ``` - 若 `cnt == m` → 该人满分 - 若 `cnt == 0` → 该人零分 - 否则 → 中间分 我们希望:能在 `n` 个人中选出恰好 `p` 个满分、`q` 个零分。 但注意:题目并没有说哪 `p` 个是满分、哪 `q` 个是零分,只要存在一种分配方式即可。 所以我们不需要知道是谁,只需要统计: - 有多少人的答案等于 `res` → 记作 full_count - 有多少人的答案等于 `not(res)` → 记作 zero_count - 其他人数为 rest_count 其中 `not(res)` 是指每一位都相反的字符串。 那么必须满足: ```cpp full_count >= p zero_count >= q 且 (n - full_count - zero_count) >= (n - p - q) // 即剩下的人足够填充非满非零部分 → 实际上等价于 full_count >= p && zero_count >= q ``` 因为总共需要选 `p` 个满分(只能从 `full_count` 中选),`q` 个零分(只能从 `zero_count` 中选),剩下的随便填。 所以只要 `full_count >= p` 且 `zero_count >= q`,就可以选出这样的组合。 于是算法如下: --- ### ✅ 算法步骤 1. 输入 `n, m, p, q` 和 `n` 个字符串 `s[0..n-1]` 2. 收集所有候选答案: - 所有 `s[i]` (可能是标准答案,若第 i 个是满分) - 所有 `flip(s[i])`(可能是标准答案,若第 i 个是零分) 3. 将这些候选加入集合,然后去重并按字典序排序 4. 遍历每个候选 `res`(从小到大),尝试验证是否合法 5. 验证方法: - 统计有多少个 `s[i] == res` → full_match - 统计有多少个 `s[i] == flip(res)` → zero_match - 若 `full_match >= p && zero_match >= q`,则 `res` 是合法答案 6. 输出第一个合法的 `res` 7. 若没有合法的,输出 `-1` --- ### 💡 注意事项 - 字符串比较可以直接用 `std::string` 的 `==` - `flip(s)` 函数:把 `'Y'` 变 `'N'`,`'N'` 变 `'Y'` - 使用 `set<string>` 自动去重+排序,然后转为 vector 并排序(其实 set 已经有序) 但注意:`set` 是红黑树,默认升序,正好是字典序。 --- ### ✅ C++ 代码实现 ```cpp #include <iostream> #include <vector> #include <set> #include <algorithm> #include <string> using namespace std; string flip(const string& s) { string t = s; for (char& c : t) { c = (c == 'Y') ? 'N' : 'Y'; } return t; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, p, q; cin >> n >> m >> p >> q; vector<string> answers(n); for (int i = 0; i < n; ++i) { cin >> answers[i]; } // 构建候选答案集合(去重 + 排序) set<string> candidateSet; for (int i = 0; i < n; ++i) { candidateSet.insert(answers[i]); candidateSet.insert(flip(answers[i])); } // 转为有序列表(已经是有序的) vector<string> candidates(candidateSet.begin(), candidateSet.end()); sort(candidates.begin(), candidates.end()); // 实际上 set 已排序 // 预先计算每个答案的翻转,避免重复计算 vector<string> flipped(n); for (int i = 0; i < n; ++i) { flipped[i] = flip(answers[i]); } // 遍历每个候选答案 for (const string& res : candidates) { int full_match = 0; // 答案完全相同的数量(满分者) int zero_match = 0; // 答案完全相反的数量(零分者) for (int i = 0; i < n; ++i) { if (answers[i] == res) { full_match++; } if (flipped[i] == res) { // 即 answers[i] 与 res 完全不同 zero_match++; } } if (full_match >= p && zero_match >= q) { cout << res << '\n'; return 0; } } // 无解 cout << "-1\n"; return 0; } ``` --- ### ⚠️ 复杂度分析 - 候选答案数:最多 `2n = 60000` - 每个候选验证需遍历 `n=30000` 个字符串,每次比较 `m=500` 字符 → 最坏 `60000 * 30000 = 1.8e9` 次操作,可能超时! 我们需要优化! --- ### ✅ 优化方案:减少候选数量 关键观察:真正有意义的候选答案只有那些能作为“某人满分或零分”的答案。 但更重要的是:**标准答案必须使得至少 p 个人与其相同,q 个人与其相反。** 我们可以反过来:只枚举 `answers[i]` 和 `flip(answers[i])`,但不去重太多也没关系,最多 `2n`。 然而最坏情况仍然不可接受。 进一步优化: 我们可以先预处理两个映射: - `countOrig[s]`: 原始答案为 s 的人数 - `countFlip[s]`: 翻转后为 s 的人数(即原串为 flip(s) 的数量) 但更好的做法是: 枚举所有 `i`,把 `answers[i]` 和 `flip(answers[i])` 加入候选集,然后对候选集去重排序。 然后对每个候选 `res`,我们快速统计: - `full_match = countOrig[res]` - `zero_match = countOrig[flip(res)]` → 因为若某人原始答案是 `t`,且 `t == flip(res)`,则 `res == flip(t)`,说明此人全错 所以我们可预先用 `map<string, int>` 统计每个原始字符串出现次数。 --- ### ✅ 优化后的代码(推荐) ```cpp #include <iostream> #include <vector> #include <set> #include <map> #include <algorithm> #include <string> using namespace std; string flip(const string& s) { string t = s; for (char& c : t) { c = (c == 'Y') ? 'N' : 'Y'; } return t; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, p, q; cin >> n >> m >> q >> q; // 注意:这里 p 和 q 都要用 cin >> n >> m >> p >> q; vector<string> answers(n); map<string, int> freq; for (int i = 0; i < n; ++i) { cin >> answers[i]; freq[answers[i]]++; } set<string> candidateSet; for (int i = 0; i < n; ++i) { candidateSet.insert(answers[i]); candidateSet.insert(flip(answers[i])); } vector<string> candidates(candidateSet.begin(), candidateSet.end()); sort(candidates.begin(), candidates.end()); for (const string& res : candidates) { int full_match = freq[res]; // 多少人答成 res(满分) int zero_match = freq[flip(res)]; // 多少人答成 flip(res),翻转后等于 res → 零分 if (full_match >= p && zero_match >= q) { cout << res << '\n'; return 0; } } cout << "-1\n"; return 0; } ``` 等等!上面有个 bug:我写了两遍 `cin >> ...`,修正一下。 --- ### ✅ 最终正确代码 ```cpp #include <iostream> #include <vector> #include <set> #include <map> #include <string> using namespace std; string flip(const string& s) { string t = s; for (char& c : t) { c = (c == 'Y') ? 'N' : 'Y'; } return t; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, p, q; cin >> n >> m >> p >> q; vector<string> answers(n); map<string, int> freq; for (int i = 0; i < n; ++i) { cin >> answers[i]; freq[answers[i]]++; } set<string> candidateSet; for (int i = 0; i < n; ++i) { candidateSet.insert(answers[i]); candidateSet.insert(flip(answers[i])); } for (const string& res : candidateSet) { int full_match = freq[res]; int zero_match = freq[flip(res)]; if (full_match >= p && zero_match >= q) { cout << res << '\n'; return 0; } } cout << "-1\n"; return 0; } ``` > 注意:`candidateSet` 是 `set`,自动按字典序排序,因此我们按顺序遍历时,第一个合法的就是字典序最小的。 --- ### ✅ 正确性保证 - 枚举了所有可能的标准答案(来自满分者或零分者的答案) - 使用哈希表 `freq` 快速统计频次 - 时间复杂度:O(2n × m) 用于构造 flip 和插入 set,O(2n × n_log?) 实际上是 O(n log n) 排序/插入,总体可接受 --- ### ❧ 总结 本题核心在于: - 标准答案必然等于某个犇的答案(若是满分)或其反串(若是零分) - 因此只需枚举这些候选 - 利用哈希表加速统计匹配人数 - 输出第一个满足 `full >= p && zero >= q` 的候选 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值