2025/8/4 模拟赛总结

\(100+20+65+20=205\),暴力挂了 \(55\) 分?

#A. 宝石展览

洛谷 P10185,之前做过。用二项式定理化简一下式子,直接算即可

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 2e5 + 5;
const LL kP = 1e9 + 7;

LL n, a[kMaxN], v[kMaxN], p, ans;

LL P(LL x, LL y, LL ret = 1) {
  for (; y; (y & 1) && ((ret *= x) %= kP), (x *= x) %= kP, y >>= 1) {
  }
  return ret;
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i], (p += a[i]) %= (kP - 1);
  }
  for (int i = 1; i <= n; i++) {
    cin >> v[i], (ans += ((P(v[i] + 1, a[i]) - 1 + kP) % kP) * P(2, (p - a[i] + kP - 1) % (kP - 1)) % kP) %= kP;
  }
  cout << ans << '\n';
  return 0;
}

#B. 乘积

因为因数成对出现,答案可以用总选择方式除以 \(2\) 来算。注意要特殊判断乘积刚好是 \(n^m\) 的情况

// BLuemoon_
#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 1.5e3 + 5, kMaxM = 205, kMaxL = 1e5 + 5;
const LL kP = 998244353;

LL n, m, tot, ans = 1, s[kMaxL], f[kMaxL];
multiset<LL> g;

LL P(LL x, LL y, LL ret = 1) {
  for (; y; (y & 1) && ((ret *= x) %= kP), (x *= x) %= kP, y >>= 1) {
  }
  return ret;
}
LL Calc(LL l, LL r) { return (s[r] - (l - 1 < 0 ? 0 : s[l - 1]) + kP) % kP; }
LL Solve(LL x) {
  fill(s, s + x * m + 1, 1), fill(f, f + x * m + 1, 0), f[0] = 1;
  for (int i = 1; i <= m << 1; i++) {
    for (int j = x * m; j; j--) {
      f[j] = Calc(j - x, j);
    }
    for (int j = 1; j <= x * m; j++) {
      s[j] = (s[j - 1] + f[j]) % kP;
    }
  }
  return f[x * m];
}
void F(LL tmp = n) {
  for (LL i = 2, cnt = 0; i * i <= tmp; i++, cnt = 0) {
    if (tmp % i == 0) {
      for (; tmp % i == 0; tmp /= i, cnt++) {
      }
      g.insert(cnt);
    }
  }
  tmp > 1 && (g.insert(1), 0);
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  for (LL i = 1; i * i <= n; i++) {
    if (n % i == 0) {
      tot++, (i * i != n) && (tot++);
    }
  }
  F();
  for (LL i : g) {
    (ans *= Solve(i)) %= kP;
  }
  cout << ((ans + P(tot, m << 1)) % kP) * P(2, kP - 2) % kP << '\n';
  return 0;
}

#C. 平面点集划分

先考虑 \(O(n^2)\) 的 dp,将每个点离散化后选择的两个集合分界线一定是一个折线。于是可以枚举每个点从下还是从左转移过来。这个过程可以用线段树优化

#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 4e5 + 5;

struct P {
  LL x, y, v;
} c[kMaxN];

LL n, T, sum, tot, p[kMaxN], f[kMaxN], g[kMaxN], ans;
vector<LL> id[kMaxN];

struct Sgt {
  LL t[kMaxN << 2], tag[kMaxN << 2];
  void pushup(LL x) { t[x] = max(t[x << 1], t[x << 1 | 1]); }
  void addtag(LL x, LL v) { t[x] += v, tag[x] += v; }
  void pushdown(LL x) { tag[x] && (addtag(x << 1, tag[x]), addtag(x << 1 | 1, tag[x]), tag[x] = 0); }
  void build(LL x, LL l, LL r) {
    t[x] = 0, tag[x] = 0;
    if (l == r) {
      return;
    }
    int mid = l + r >> 1;
    build(x << 1, l, mid), build(x << 1 | 1, mid + 1, r);
    pushup(x);
  }
  void update(LL x, LL l, LL r, LL L, LL R, LL v) {
    if (L <= l && r <= R) {
      return addtag(x, v), void();
    }
    pushdown(x);
    int mid = l + r >> 1;
    L <= mid && (update(x << 1, l, mid, L, R, v), 0);
    mid < R && (update(x << 1 | 1, mid + 1, r, L, R, v), 0);
    pushup(x);
  }
  LL query(LL x, LL l, LL r, LL L, LL R, LL ret = -1e18) {
    if (L <= l && r <= R) {
      return t[x];
    }
    pushdown(x);
    int mid = l + r >> 1;
    L <= mid && (ret = max(ret, query(x << 1, l, mid, L, R)));
    R > mid && (ret = max(ret, query(x << 1 | 1, mid + 1, r, L, R)));
    return ret;
  }
} tr, tr2;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  cin.tie(0)->ios::sync_with_stdio(0);
  for (cin >> T; T; T--, tot = sum = ans = 0) {
    cin >> n;
    for (LL i = 1, a, b; i <= n; i++) {
      cin >> c[i].x >> c[i].y >> a >> b, sum += a, c[i].v = b - a, p[++tot] = c[i].x, p[++tot] = c[i].y;
    }
    p[++tot] = 0, sort(p + 1, p + 1 + tot), tot = unique(p + 1, p + 1 + tot) - p - 1;
    for (int i = 1; i <= n; i++) {
      c[i].x = lower_bound(p + 1, p + 1 + tot, c[i].x) - p, c[i].y = lower_bound(p + 1, p + 1 + tot, c[i].y) - p;
    }
    for (int i = 1; i <= tot; i++) {
      id[i].clear();
    }
    for (int i = 1; i <= n; i++) {
      id[c[i].x].push_back(i);
    }
    tr.build(1, 1, tot), tr2.build(1, 1, tot);
    for (int i = 1; i <= n; i++) {
      tr2.update(1, 1, tot, c[i].y, tot, c[i].v), tr.update(1, 1, tot, c[i].y, tot, -c[i].v);
    }
    f[1] = 0;
    for (int i = 2; i <= tot; i++) {
      f[i] = -1e18, tr.update(1, 1, tot, i, i, -1e18);
    }
    for (int i = 1; i <= tot; i++) {
      for (LL k : id[i]) {
        LL j = c[k].y;
        g[j] = f[j], f[j] = max(f[j], tr.query(1, 1, tot, 1, j - 1) + tr2.query(1, 1, tot, j, j)), ans = max(ans, f[j]);
      }
      for (LL k : id[i]) {
        LL j = c[k].y;
        tr.update(1, 1, tot, j, j, f[j] - g[j]), tr2.update(1, 1, tot, j, tot, -c[k].v), tr.update(1, 1, tot, j, tot, c[k].v);
      }
    }
    cout << sum + ans << '\n';
  }
  return 0;
}

#D. 阻碍

TBD...

posted @ 2025-08-04 17:00  BluemoonQwQ  阅读(21)  评论(0)    收藏  举报