说怪话

P6196 [EER1] 代价

将操作倒着想,容易想到在两个 1 的中间加数代价小。

code
const int N = 1e6 + 5;

int n, a[N], cnt;
i64 pre[N], suf[N], ans;

int main() {
  read(n); a[0] = a[n + 1] = 1;
  rep(i, 1, n) read(a[i]);

  for (int l = 0, r = 1; r <= n + 1; l = r, r++) {
    while (a[r] != 1) r++;
    cnt++;
    if (l + 1== r) continue;
    i64 res = 2e18;
    rep(i, l + 1, r - 1) pre[i] = (i64)a[i] * a[i + 1];
    per(i, r - 1, l + 1) suf[i] = (i64)a[i] * a[i - 1];
    rep(i, l + 1, r - 1) pre[i] += pre[i - 1];
    per(i, r - 1, l + 1) suf[i] += suf[i + 1];
    rep(i, l + 1, r - 1) chkmin(res, pre[i - 1] + suf[i + 1] + a[i]);
    ans += res;
  }

  ans += cnt - 1;
  write(ans);
  return 0;
}

P6381 『MdOI R2』Odyssey

容易想到拓扑排序计算最长路,有 \(\mathcal{O}(\sum\limits_{i = 1}^{n}in(i)\times out(i))\) 的做法。

考虑到问题在于对于边一对一匹配,这很慢。自然能想到进行集合。

\(w\) 进行质因数分解,得到 \(w = \sum\limits_{i = 1, p_i\mid w}p_i^{k_i}\)。将 \(w\) 映射为 \(w' = \sum\limits_{i = 1, p_i\mid w}p_i^{k_i \bmod k}\)。这样对于 \(w'\),与其匹配的边是唯一的。

DP 显然。复杂度为 \(\mathcal{O}(n + m)\)

code
const int N = 1e5 + 5;

int n, m, k, ans;
unordered_map<int, int> f[N];

int tran(int x) {
  i64 res = 1;

  rep(i, 2, sqrt(x)) if (x % i == 0) {
    int c = 0; while (x % i == 0) c++, x /= i;
    c %= k; while (c--) res *= i;
  }

  if (x > 1 && k > 1) res *= x; 
  return res;
}

int ope(int x) {
  i64 res = 1;

  rep(i, 2, sqrt(x)) if (x % i == 0) {
    int c = 0; 
    while (x % i == 0) c++, x /= i;
    c %= k; 
    if (c) {
      c = k - c; 
      while (c--) { 
        res *= i;  
        if (res > 1e5) return -1; 
      }
    }
  }

  if (x > 1 && k > 1) { 
    rep(i, 1, k - 1) {
      res *= x;
      if (res > 1e5) return -1;
    }
  }

  return res;
}

struct Graph {
  int head[N], ver[N << 1], edge[N << 1], wgt[N << 1], Next[N << 1], tot = 1, ind[N], pw[N << 1];

  void add(int u, int v, int w, int l) {
    Next[++tot] = head[u]; ind[v]++;
    ver[head[u] = tot] = v, edge[tot] = l, wgt[tot] = tran(w), pw[tot] = ope(w);
  }
} DAG;

void topo() {
  queue<int> que;
  rep(i, 1, n) if (!DAG.ind[i]) que.push(i);

  while (que.size()) {
    int u = que.front(); que.pop();

    for (int i = DAG.head[u]; i; i = DAG.Next[i]) {
      int v = DAG.ver[i], w = DAG.wgt[i], iw = DAG.pw[i], l = DAG.edge[i];
      chkmax(f[v][w], f[u][iw] + l);
      chkmax(ans, f[v][w]);
      if (!(--DAG.ind[v])) que.push(v);
    }
  }
}

int main() {
  read(n, m, k);

  rep(i, 1, m) { 
    int u, v, w, l; 
    read(u, v, w, l);
    DAG.add(u, v, w, l);
  }

  topo();
  write(ans, '\n');
  return 0;
}

时间复杂度算错,原因是对时间复杂度模糊的地方没有细想

补题时输入格式写错,虚空调试30min,牛大了

P10675 【MX-S1-T4】先见之明

找到满足 \(\sum\limits_{i = j}^m 2^{p_i} > \sum\limits_{a_x \le p_j} 2^{a_x}\) 的最小的 \(j\),令 \(\min\limits_{a_i > p_j}\{a_i\} = a_u\),答案为 \(\sum\limits_{i = 1}^j2^{p_i} + 2^{a_u}\)

考虑如何求该位置。

定义 \(g(i)\) 表示 \(\sum\limits_{a_x \le i} 2^{a_x}\) 的最高位,\(h(i) = \sum\limits_{j = i}^m 2^{p_j}\)\(g(i) > i\)\(i\) 显然不是所求,\(g(i) < i\) 时显然是。

讨论 \(g(i) = i\) 的情况。定义 \(f(i)=[\sum\limits_{a_x \le p_j} 2^{a_x} < h(i)]\)。注意到此时相当与两个后缀字符串进行比较。

如果有 \(a_x \in(p_{i - 1}, p_i)\)\(f(i) = 1\),否则,答案取决于 \(f(i + 1)\)

点击查看代码
const int N = 1e6 + 30;
const int mod = 998244353;

int n, q, s[N], c[N], mp[N], v = N - 10, ps[N], pc[N];
bool f[N];
int pw[N];

void solve() {
  int m; read(m); vector<int> p(m + 1);
  rep(i, 1, m) read(p[i]); f[m + 1] = 1;
  int bk = m + 1, ans = 0;
  per(i, m, 1) {
    if (i < m && ps[p[i + 1] + 1] < p[i]) f[i + 1] = 1;
    f[i] = s[p[i]] ? f[i + 1] : 0;
    if (!f[i] && mp[p[i]] <= p[i]) bk = i;
  }

  rep(i, 1, bk - 1) ans = (ans + pw[p[i]]) % mod;
  if (bk <= m) ans = pc[p[bk] + 1] == -1 ? -1 : (ans + pw[pc[p[bk] + 1]]) % mod;
  write(ans, '\n');
}

int main() {
  pw[0] = 1;
  rep(i, 1, v) pw[i] = 2 * pw[i - 1] % mod;
  read(n, q);
  rep(i, 1, n) {
    int x; read(x);
    c[x]++;
  }

  int mx = -1;
  rep(i, 0, v) {
    s[i] += c[i];
    int j = i;
    while (s[j] > 1) {
      s[j + 1] += s[j] / 2;
      s[j] &= 1; j++;
      chkmax(mx, j);
    }

    mp[i] = mx;
  }

  ps[v] = pc[v] = -1;
  per(i, v - 1, 0) {
    ps[i] = s[i] ? i : ps[i + 1];
    pc[i] = c[i] ? i : pc[i + 1];
  }

  while (q--) solve();
  return 0;
}
posted @ 2025-11-04 20:51  FRZ_29  阅读(6)  评论(1)    收藏  举报
2025-7-11 11:06:15 TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 FRZ - 1801534592@qq.com
Illustration from たとえ,by Rella