2024/09/29 模拟赛总结

0+0+0+0=0,感觉不如 #include <bits./stdc++.h>

#A. 你相信()吗

70 分的 O(n3) 算法很好解决,枚举出三盏灯的亮度后,剩下一个灯的亮度一定固定。对于每个格子剩余亮度需求取 max 即可。

然后我们充分发扬人类智慧,当 n400 时跑暴力,否则考虑推式子,下面的 = 表示大概相等

i,j,k,e 分别为左上,右上,左下,右下灯的亮度

{a=i+j2+k2+e4b=j+i2+k4+e2c=k+i2+j4+e2d=e+i4+j2+k2

我们枚举 i,j,令 k=k2,e=e2,对于后两个式子进行移项,得到:

{ci2+j4=k+e2=2k+eF1di4j2=e+k2=2e+kF2

e,k 当成未知数解方程,得到 k=F1F1+F23,e=F2F1+F23

然后因为这是大概范围,需要左右偏移找答案,偏移值 35 左右就可以了

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

using namespace std;
using LL = long long;

LL a, b, c, d, e, c3, c4, ed, k, v, v_, ed_, ans = 1e18;

int main() {
  freopen("light.in", "r", stdin), freopen("light.out", "w", stdout);
  cin >> a >> b >> c >> d;
  if (a <= 400 && b <= 400 && c <= 400 && d <= 400) {
    for (int i = 0; i <= a; i++) {
      for (int j = 0; j <= b; j++) {
        for (int k = 0; k <= c; k++) {
          e = max({0ll, d - i / 4 - j / 2 - k / 2, (a - i - j / 2 - k / 2) << 2, (b - j - i / 2 - k / 4) << 1, (c - j / 4 - i / 2 - k) << 1}), ans = min(ans, i + j + k + e);
        }
      }
    }
    cout << ans << '\n';
    return 0;
  }
  for (int i = 0; i <= a; i++) {
    for (int j = 0; j <= b; j++) {
      c3 = c - i / 2 - j / 4, c4 = d - j / 2 - i / 4, v = c3 - (c3 + c4) / 3, v_ = c4 = (c3 + c4) / 3, v <<= 1, v_ << 1, ed = min(c, v + 35), ed_ = min(d, v_ + 35);
      for (int k = max(0ll, v - 35); k <= ed; k++) {
        e = max({0ll, d - i / 4 - j / 2 - k / 2, (a - i - j / 2 - k / 2) << 2, (b - j - i / 2 - k / 4) << 1, (c - j / 4 - i / 2 - k) << 1}), ans = min(ans, i + j + k + e);
      }
      for (int e = max(0ll, v_ - 35); e <= ed_; e++) {
        k = max({0ll, (d - i / 4 - j / 2 - e) << 1, (a - i - j / 2 - e / 4) << 1, (b - j - i / 2 - e / 2) << 2, c - j / 4 - i / 2 - e / 2}), ans = min(ans, i + j + k + e);
      }
    }
  }
  cout << ans << '\n';
  return 0;
}

#B. 爪巴

O(2n) 拿了 80 哈哈

对于一个节点,它每一位二进制的贡献为 2tot1tot 为这个点以及其直接儿子当前二进制位为 1 的数的数量

因为只有数量为数量为奇数才能满足,所以数量为 Ctot1+Ctot3+=2tot1

然后枚举其他蚂蚁是否移动,记得特判根节点不能移动的情况

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

using namespace std;
using LL = long long;

const LL kP = 1e9 + 7;
const int kMaxN = 1e5 + 5, kL = 31 + 5;

int n;
LL a[kMaxN], ans, f[kMaxN], p[kMaxN], tot = 1, l, r;
vector<int> g[kMaxN];

void Calc(int x, int *e) {
  for (int i = 0; i <= 30; e[i] += (x & 1), x >>= 1, i++) {
  }
}
void DFS(int u) {
  int e[kL], tot = 1;
  fill(e, e + kL, 0), Calc(a[u], e);
  for (int v : g[u]) {
    DFS(v), Calc(a[v], e), tot++;
  }
  if (tot != 1) {
    l = p[tot - 1 - (u == 1)], r = p[n - tot - (u != 1)];
    for (int i = 0; i <= 30; i++) {
      if (e[i]) {
        LL tmp = 1 << i, w = l;
        if (u == 1 && (e[i] == 1) && (a[u] & (1 << i))) {
          (w <<= 1) %= kP;
        }
        (ans += (tmp * w % kP) * r % kP) %= kP;
      }
    }
    (ans -= a[u] * r % kP) %= kP, (ans += kP) %= kP;
    if (u != 1) {
      for (int v : g[u]) {
        (ans -= a[v] * r % kP) %= kP, (ans += kP) %= kP;
      }
    }
  }
}

int main() {
  freopen("climb.in", "r", stdin), freopen("climb.out", "w", stdout);
  p[0] = 1;
  for (int i = 1; i < kMaxN; i++) {
    p[i] = (p[i - 1] << 1) % kP;
  }
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 2, x; i <= n; i++) {
    cin >> x, g[x].push_back(i);
  }
  DFS(1);
  cout << ans << '\n';
  return 0;
}   

#C. sTrINg

考虑贪心,由于 cntA1a 一定不大于 1,显然大部分情况下 A 都只会放一个

我们枚举 A 和 B 经过了多少次交换,当 B 不够放时,只能先放完 A 再放完 B,否则剩下的 B 一定是放 b+1 个就换成 A ,多余的 A 一起放

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

using namespace std;

const int kMaxN = 2e5 + 5;

int t, n, m, a, b, c, ans, f[kMaxN], x;

int main() {
  freopen("string.in", "r", stdin), freopen("string.out", "w", stdout);
  for (cin >> t; t; t--, ans = 0) {
    cin >> n >> m >> a >> b >> c;
    for (int i = 0; i <= min(n, m / c); i++) {
      if (i == 0) {
        x += (n - 1) / a + (m - 1) / b + 1;
      } else {
        x += (i << 1) - 1;
        (n - i >= 1) && (x += 1 + (n - i - 1) / a);
        (c > b) && (x += (c - 1) / b * i);
        if (m >= 1 + c * i) {
          x++;
          int e = m - i * c - 1, k = ((c - 1) / b + 1) * b - c + 1;
          (e / k >= i) ? (x += i, e -= k * i) : (x += e / k, e -= e / k * k);
          x += e / b;
        }
      }
      ans = max(ans, x), x = 0;
    }
    cout << ans + 1 << '\n';
  }
  return 0;
}

#D. Fucktion

你说得对,但是我觉得不如 O(nq)

考虑特殊性质 A,我们知道 f(x) 是一个形如

f(x)={AxaCxbx+Belse

的分段函数

于是我们二分这个这两个断点,就可以 O(1) 回答询问了

如果你问我剩下 75 分怎么做,请注意观察第一句话

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

using namespace std;
using LL = long long;

const int kMaxN = 3e5 + 5;

int n, q, op[kMaxN], v[kMaxN], k, l, r, L, R, o, Q[kMaxN][3], fmn, fmx;

int Calc(int x) {
  for (int i = 1; i <= n; i++) {
    if (op[i] == 1) {
      x += v[i];
    } else if (op[i] == 2) {
      x = min(x, v[i]);
    } else {
      x = max(x, v[i]);
    }
  }
  return x;
}
bool Chk() {
  for (int i = 1; i <= q; i++) {
    if (Q[i][0] != 4) {
      return 0;
    }
  }
  return 1;
}

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  freopen("function.in", "r", stdin), freopen("function.out", "w", stdout);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> op[i] >> v[i];
  }
  cin >> q;
  for (int i = 1; i <= q; i++) {
    cin >> Q[i][0] >> Q[i][1], (Q[i][0] != 4) && (cin >> Q[i][2], 1);
  }
  if (Chk()) {
    fmn = Calc(-1e9), fmx = Calc(1e9);
    for (l = -1e9, r = 1e9; l < r;) {
      int mid = (l + r) >> 1;
      (Calc(mid) == fmn) ? l = mid + 1 : r = mid - 1;
    }
    L = l - 1;
    for (l = -1e9, r = 1e9; l < r;) {
      int mid = (l + r) >> 1;
      (Calc(mid) == fmx) ? r = mid - 1 : l = mid + 1;
    }
    R = r + 1;
    int gengar = Calc(L + 1) - L - 1;
    for (int i = 1; i <= q; i++) {
      if (Q[i][1] > L && Q[i][1] < R) {
        cout << gengar + Q[i][1] << '\n';
      } else if (Q[i][1] <= L) {
        cout << fmn << '\n';
      } else {
        cout << fmx << '\n';
      }
    }
    return 0;
  }
  for (int i = 1; i <= q; i++) {
    k = Q[i][0], r = Q[i][1];
    if (k <= 3) {
      op[r] = k, v[r] = Q[i][2];
    } else {
      for (int i = 1; i <= n; i++) {
        if (op[i] == 1) {
          r += v[i];
        } else if (op[i] == 2) {
          r = min(r, v[i]);
        } else {
          r = max(r, v[i]);
        }
      }
      cout << r << '\n';
    }
  }
  return 0;
}
posted @   BluemoonQwQ  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示