CF1845F Swimmers in the Pool 题解
思路#
考虑两个人什么时候会相遇。
根据小学的相遇追及问题,两人会相遇的条件为:
那么对于一个速度
它可一相遇的次数即为:
当然,这样有可能会算重,也就是在相同的时间算了多次答案。
注意到若两个
所以可以更改一下式子:
可以直接枚举倍数计算。
至于如何求出所有的
可以看作两个多项式:
算出
时间复杂度:
Code#
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
// #define int long long
#define mp(x, y) make_pair(x, y)
#define eb(...) emplace_back(__VA_ARGS__)
#define fro(i, x, y) for(int i = (x); i <= (y); i++)
#define pre(i, x, y) for(int i = (x); i >= (y); i--)
inline void JYFILE19();
typedef long long i64;
typedef pair<int, int> PII;
bool ST;
const int N = 2e6 + 10;
const int M = 2e5;
const int mod = 998244353;
const int Mod = 1e9 + 7;
int l, t, n, ans, v[N], f[N], g[N], h[N], dp[N];
inline i64 power(i64 x, i64 y) {
i64 res = 1;
while(y) {
if(y & 1) res = res * x % mod;
x = x * x % mod, y /= 2;
}
return res;
}
struct ntt {
int m, tp, b[N], w[N];
int g = 3, ig = power(3, mod - 2);
#define Add(x, y) ((x + y >= mod) ? x + y - mod : x + y)
#define Sub(x, y) ((x - y >= 0) ? x - y : x - y + mod)
inline void init(int n) {
if(m == (1<<__lg(n)+1)) return; m = (1<<__lg(n)+1);
fro(i, 0, m - 1) b[i] = (b[i>>1]>>1)|((i&1)?m>>1:0);
}
inline void NTT(int *f, int n) {
init(n), w[0] = 1; int iv = (tp?power(m,mod-2):1);
fro(i, 1, m) if(i < b[i]) swap(f[i], f[b[i]]);
for(int p = 1; p < m; p <<= 1) {
int s = p<<1, b = power(tp?ig:g,(mod-1)/s);
for(int i = p - 2; i >= 0; i -= 2)
w[i | 1] = 1ll * b * (w[i] = w[i>>1]) % mod;
for(int i = 0; i < m; i += s) fro(j, 0, p - 1) {
int x = f[i + j], y = 1ll * f[i + j + p] * w[j] % mod;
f[i + j] = Add(x, y), f[i + j + p] = Sub(x, y);
}
}
if(tp) fro(i, 0, m - 1) f[i] = 1ll * f[i] * iv % mod;
}
inline void times(int *f, int *g, int n) {
tp = 0, NTT(f, n), NTT(g, n);
fro(i, 0, m - 1) f[i] = 1ll * f[i] * g[i] % mod;
tp = 1, NTT(f, n);
fill(g, g + m, 0);
fill(f + n + 1, f + m, 0);
}
} sol;
signed main() {
JYFILE19();
cin >> l >> t >> n;
fro(i, 1, n) cin >> v[i];
fro(i, 1, n) f[M + v[i]] = 1;
fro(i, 1, n) g[M + v[i]] = 1;
sol.times(f, g, M * 4);
fro(i, 0, M * 2) dp[i] = max(f[i + M * 2], dp[i]);
fro(i, 1, n) dp[v[i] * 2]--;
memset(f, 0, sizeof f);
memset(g, 0, sizeof g);
fro(i, 1, n) f[M + v[i]] = 1;
fro(i, 1, n) g[M - v[i]] = 1;
sol.times(f, g, M * 4);
fro(i, 0, M * 2) dp[i] = max(f[i + M * 2], dp[i]);
fro(i, 1, M * 2) {
for(int j = 1; j * i <= M * 2; j++) {
dp[i] = max(dp[i], dp[j * i]);
}
}
fro(i, 1, M * 2) {
(h[i] += (1ll * i * t / (l * 2)) % Mod) %= Mod;
for(int j = 2; j * i <= M * 2; j++)
(h[i * j] += Mod - h[i]) %= Mod;
if(dp[i] > 0) (ans += h[i]) %= Mod;
}
cout << ans << "\n";
return 0;
}
bool ED;
inline void JYFILE19() {
// freopen("", "r", stdin);
// freopen("", "w", stdout);
ios::sync_with_stdio(0), cin.tie(0);
double MIB = fabs((&ED-&ST)/1048576.), LIM = 512;
cerr << "MEMORY: " << MIB << endl, assert(MIB<=LIM);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)