Loading

CF1845F Swimmers in the Pool 题解

思路

考虑两个人什么时候会相遇。

根据小学的相遇追及问题,两人会相遇的条件为:

\[2\times k\times l=t\times (v1+v2) \]

\[2\times k\times l=t\times (v1-v2) \]

那么对于一个速度 \(v\)

它可一相遇的次数即为:

\[\frac{t\times v}{2\times l} \]

当然,这样有可能会算重,也就是在相同的时间算了多次答案。

注意到若两个 \(v\) 有倍数关系,那么就会算重答案。

所以可以更改一下式子:

\[f_v=\frac{t\times v}{2\times l}-\sum_{i=1}^{i<v}[i|v] f_i \]

可以直接枚举倍数计算。

至于如何求出所有的 \(v\) 是否等于 \(v1+v2\) 或者 \(v1-v2\)

可以看作两个多项式:

\[f=x^{v_1}+x^{v_2}+x^{v_3}+x^{v_4}\cdots \]

\[g=x^{-v_1}+x^{-v_2}+x^{-v_3}+x^{-v_4}\cdots \]

算出 \(f\)\(f\)\(f\)\(g\) 的卷积即可,可以使用 ntt 加速。

时间复杂度:\(O(v\ln v+v\log v)\)

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);
}
posted @ 2024-02-22 20:16  JiaY19  阅读(4)  评论(0编辑  收藏  举报