2025.2.20 CW 模拟赛
T1
算法
概率, 期望.
思路
根据期望的线性性, 可得第 1 堆石子被取走的期望时间 \(\displaystyle E(t) = 1 + \sum_{i = 2}^n P_i\), 其中 \(P_i\) 指的是第 \(i\) 堆石子在「第 1 堆石子被取走前」取走的概率.
注意到 \(P_i\) 只与第 1 堆和第 \(i\) 堆石子有关, 因此相当于只考虑这两堆的情况, 即 \(\displaystyle P_i = \frac{a_i}{a_1 + a_i}\).
这样最后的答案即为 \(\displaystyle 1 + \sum_{i = 2}^{n} \frac{a_i}{a_1 + a_i}\), 时间复杂度 \(\mathcal{O}(n)\).
double ans = 1;
for (int i = 2; i <= n; ++i)
ans += 1.0 * a[i] / (a[i] + a[1]);
T2
算法
二分.
思路
发现 \(m \le 1000\), 我们可以考虑枚举每一个 \(x\), 再二分查找最小的最大值, \(\rm{check}\) 时贪心即可. 时间复杂度 \(\Theta (nm\log n)\).
将原序列随机打乱再遍历, 令答案为 \(ans - 1\) 再 \(\rm{check}\), 判断当前 \(x\) 是否满足条件. 这样只会二分 \(\mathcal{O}(\ln n)\) 次, 总时间复杂度 \(\mathcal{O}(nm + n \ln n \log n)\).
T3
算法
质因数分解, 容斥.
思路
首先可以知道若一个数不为 \(n\) 的约数, 如果将其选入子集, 那么 \(\rm{lcm}\) 一定不为 \(n\). 于是我们只有在 \(n\) 的因数中选择并加入子集.
现在考虑 \(\gcd = 1, \rm{lcm} = n\) 两个约束. 我们令 \(\displaystyle n = \prod p_i^{\alpha_i}\), 如果集合 \(\mathbb{S}\) 的 \(\gcd\) 为 1, 那么对于每一个 \(p_i\) 均存在至少一个数在 \(p_i\) 中是 0 次方; 同理 \(\rm{lcm}\) 为 \(n\), 代表对于每一个 \(p_i\) 均存在至少一个数在 \(p_i\) 中是 \(\alpha_i\) 次方.
不妨设 \(\omega(n)\) 为 \(n\) 所含有的质因子个数, 显然, 当 \(n \le 10^{18}, \omega(n) \le 15\). 正难则反, 我们考虑使用容斥计算方案数. 具体的, 我们用所有情况去掉不存在 0 次方的情况, 再去掉不存在 \(\alpha\) 次方的情况, 最后加上都不存在的情况即可. 这样, 对于每一个质因子, 我们需要枚举 4 种情况, 总时间复杂度 \(\mathcal{O}(\sqrt n + 4^{\omega(n)} \cdot \omega(n))\).
事实上, 对于质因子情况的枚举是可以优化的. 对于不存在 0 次方 / 不存在 \(\alpha\) 次方的情况是完全等价的, 所以我们只需要枚举一种再在统计答案的时候加上即可. 这样枚举的复杂度降为了 \(\mathcal{O}(3^{\omega(n)} \cdot \omega(n))\), 可以过掉 \(n \le 10^{15}\).
而对于 \(n \le 10^{18}\), 瓶颈就在于分解质因数了. 我们考虑先分解出 \(\sqrt[3]{n}\) 以内的质因数, 剩下的部分只会有 \(p, p ^ 2, pq\) 三种情况, 其中 \(p, q\) 均为素数. 我们使用素性测试判断第一种情况, 再开根判断第二种情况, 那么剩下的就是第三种了. 时间复杂度 \(\mathcal{O}(\sqrt[3]{n} + 3^{\omega(n)} \cdot \omega(n) \cdot \log n)\), 其中带的 \(\log n\) 是因为快速幂, 也可以光速幂 \(\mathcal{O}(\sqrt p)\) 预处理 \(\mathcal{O}(1)\) 查询.
#include "iostream"
#include "cmath"
#include "random"
#include "vector"
using namespace std;
typedef long long ll;
constexpr int mod = 998244353;
constexpr int pow3[] = {1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907};
ll n;
vector<int> v;
ll qpow(ll x, ll y, const ll Mod = mod) {
ll ans = 1;
for (; y; y >>= 1, x = (__int128)x * x % Mod) if (y & 1) ans = (__int128)ans * x % Mod;
return ans;
}
bool check(ll x) {
mt19937_64 rnd(time(0));
if (x < 3) return x == 2;
for (int i = 1; i <= 20; ++i) {
ll t = rnd() % (n - 2) + 2;
if (qpow(t, x - 1, x) ^ 1) return false;
}
return true;
}
void deal(ll x) {
ll t = round(sqrt(x));
if (t * t == x) {
v.push_back(2);
return;
}
v.push_back(1);
if (!check(x)) v.push_back(1);
}
void init() {
cin >> n;
ll t = n;
if (n > 1e15) {
for (int i = 2, c, lim = cbrt(n); i <= lim; ++i)
if (!(t % i)) {
c = 0;
while (!(t % i)) ++c, t /= i;
v.push_back(c);
}
if (t > 1) deal(t);
}
else {
for (int i = 2, c, lim = sqrt(n); i <= lim; ++i)
if (!(t % i)) {
c = 0;
while (!(t % i)) ++c, t /= i;
v.push_back(c);
}
if (t > 1) v.push_back(1);
}
}
void calculate() {
int sz = v.size(), ans = 0;
for (int i = 0, lim = qpow(3, sz); i < lim; ++i) {
int c = 1, t = 1, cnt = 0, c1 = 0;
for (int j = 0, pw, tmp; j < sz; ++j) {
pw = v[j], tmp = i / pow3[j] % 3;
t = 1ll * t * (pw + 1 - tmp) % mod;
cnt += tmp, c1 += tmp == 1;
}
if (cnt & 1) c = -1;
ans = (ans + c * qpow(2, t + c1) + mod) % mod;
}
cout << ans << '\n';
}
void solve() {
init();
calculate();
}
int main() {
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现