26牛客暑假多校4
点击查看题面
I题 Rounddog II
题目大意
给定一个字符串 "Rounddo" 后接 'g' 组成的模式串,即:
考虑
数据范围:
- 测试用例数:
- 字符串长度:
,所有测试用例的 之和满足 - 整数
: - 字符集:
仅包含大写和小写英文字母
思路
本题的核心在于破环成链以及对匹配位置的组合计数与边界分析。
- 目标串构造: 根据题意构造目标字符串
,其长度为 。 - 边界剪枝: 若原串长度
,则 的任何循环移位都不可能包含长度更大的 ,直接输出 。 - 破环成链与匹配计数: 将字符串
复制一份拼接在其后,形成长度为 的扩展字符串 。 遍历 前半部分(即起始下标在 范围内)中所有 的出现位置,统计匹配次数 。 - 分类讨论与数学推导:
- 情况 1 (
): 说明原串及其循环拼接中完全不包含 ,因此包含 的循环移位数量为 。 - 情况 2 (
): 假设 在 中仅在下标 ( ) 处匹配成功一次。 每一个循环移位对应 中一个长度为 的滑动窗口 ( )。 该窗口能完整包含 的合法起始点 分为两类: - 覆盖第一个
(区间 ):需要 且 。由于 ,此条件下仅有 这一种合法情况。 - 覆盖第二个
(区间 ):需要 。 - 综上,合法起始点
的总数为:
此公式结果与具体的匹配位置
- 情况 3 (
): 当 在 中出现至少两次时,两次匹配覆盖的合法移位区间相互重叠并无缝衔接,覆盖了所有 个可能的循环移位起始点,因此合法移位数量为 。
复杂度分析
时间复杂度: 对于每个测试用例,构造模式串耗时 std::string::find 完成,平均耗时为
空间复杂度: 需要存储拼接串
参考代码
参考代码
c++
#include <iostream>
#include <string>
using namespace std;
using ll = long long;
void fc() {
string s;
int k;
cin >> s >> k;
string ch = "Rounddo" + string(k, 'g');
if (s.size() < ch.size()) {
cout << 0 << "\n";
return;
}
int cnt = 0;
size_t n = s.size();
s += s;
for (size_t pos = s.find(ch); pos != string::npos && pos < n; pos = s.find(ch, pos + 1)) {
cnt++;
}
if (!cnt) {
cout << 0 << "\n";
} else {
cout << (cnt == 1 ? n - ch.size() + 1 : n) << "\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
while (t--) {
fc();
}
return 0;
}B题 Quadratic Residue
题目大意
给定一个正整数
且
若存在多组解,输出任意一组合法整数;若不存在解,则输出 Impossible。
数据范围:
- 测试用例数:
- 正整数
:
思路
本题是一道巧用代数构造解决模同余问题的数论题。
- 同余方程组的代数化简: 考虑第一个同余条件
,这意味着 是 的整数倍。 最直接的构造方式是取 1 倍关系,即令:
此时,条件
由此可知,只需令
- 需要满足
。 解一元二次方程 的正根为:
为了保证整数且严格满足不等式,可取:
- 当
时,由于 ,必然满足 。 - 同时,
,当 时, ,完全满足范围限制。
- 小数据特判: 对于
和 的边界情况,可以通过直接手算构造出合法解:
:取 。 :取 。
复杂度分析
时间复杂度: 对于每个测试用例,计算
空间复杂度: 仅使用常数个辅助变量,空间复杂度为
参考代码
参考代码
c++
#include <iostream>
#include <cmath>
using namespace std;
using ll = long long;
void fc() {
ll p;
cin >> p;
if (p == 2) {
cout << "12 1 71\n";
return;
}
if (p == 3) {
cout << "4 2 13\n";
return;
}
ll x1 = (1 + (ll)sqrt(1 + 4 * p)) / 2 + 1;
ll q = x1 * x1 - p;
cout << x1 << ' ' << x1 << ' ' << q << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
while (t--) {
fc();
}
return 0;
}