《如 何 速 通 一 套 题》9.0

邮寄

开场 A 写了 70,然后写 C。

C 大样例过了。

然后 D 写了 30 走人。

B 在知晓题意后,过了样例。

然后撤退了。

70+0+40+50=160。

A 光

我们先预处理出 \(a, b, c, d \le 14\) 的答案(待会儿要考)。

然后,有一种贪心思路:

每次找到亮度需求最多的地方,加上 \(4\) 点亮度,重新计算贡献。

\(a, b, c, d \le 14\),直接输出(如果你不知道为什么,那么等待你的将会是 WA 20pts)。

#include <bits/stdc++.h>
using namespace std;

int a, b, c, d, as[50][50][50][50], ans;

int check(int x, int y, int z, int w, int ra, int rb, int rc, int rd) {
  if(ra + rb / 2 + rc / 2 + rd / 4 < x) {
    return 0;
  }
  if(rb + ra / 2 + rd / 2 + rc / 4 < y) {
    return 0;
  }
  if(rc + ra / 2 + rd / 2 + rb / 4 < z) {
    return 0;
  }
  if(rd + rb / 2 + rc / 2 + ra / 4 < w) {
    return 0;
  }
  return 1;
}

int cal(int a, int b, int c, int d) {
  int ans = 155555;
  for(int i = 0; i <= a && i <= ans; i++) {
    for(int j = 0; j <= b && i + j <= ans; j++) {
      for(int k = 0; k <= c && i + j + k <= ans; k++) {
        for(int l = 0; l <= d && i + j + k + l <= ans; l++) {
          if(check(a, b, c, d, i, j, k, l)) {
            ans = min(ans, i + j + k + l);
          }
        }
      }
    }
  }
  return ans;
}

int main() {
  freopen("light.in", "r", stdin);
  freopen("light.out", "w", stdout);
  for(int i = 0; i <= 14; i++) {
    for(int j = 0; j <= 14; j++) {
      for(int k = 0; k <= 14; k++) {
        for(int l = 0; l <= 14; l++) {
          as[i][j][k][l] = cal(i, j, k, l);
        }
      }
    }
  }
  cin >> a >> b >> c >> d;
  for(; a >= 15 || b >= 15 || c >= 15 || d >= 15; ) {
    int tmp = max({a, b, c, d});
    ans += 4;
    if(a == tmp) {
      a -= 4, b -= 2, c -= 2, d -= 1;
    }else {
      if(b == tmp) {
        b -= 4, a -= 2, d -= 2, c -= 1;
      }else {
        if(c == tmp) {
          c -= 4, a -= 2, d -= 2, b -= 1;
        }else {
          d -= 4, b -= 2, c -= 2, a -= 1;
        }
      }
    }
    a = max(a, 0), b = max(b, 0), c = max(c, 0), d = max(d, 0);
  }
  cout << ans + as[a][b][c][d] << '\n';
  return 0;
}

B 爬

讲简单点,就是子集异或和之和。

可以拆位,一位一位统计贡献。

#include <bits/stdc++.h>
#define int ll
using namespace std;
using ll = long long;

const int kMod = int(1e9) + 7;

int n, arr[100010], sum, f;
vector<int> ch[100010];

int qpow(int x, int y) {
  int rs = 1;
  for(; y; y >>= 1) {
    if(y & 1) {
      rs = rs * x % kMod;
    }
    x = x * x % kMod;
  }
  return rs;
}

int cal(const vector<int> &x, int c, bool f = 0) {
  int ans = 0;
  for(int i = 30; i >= 0; i--) {
    int c1 = 0, c0 = 0;
    for(auto j : x) {
      c1 += ((j >> i) & 1);
      c0 += !((j >> i) & 1);
    }
    if(!((c >> i) & 1)) {
      if(c1) {
        ans = (ans + (qpow(2, c0) * qpow(2, c1 - 1) - (!f) * c1 + kMod) % kMod * qpow(2, i)) % kMod;
      }
    }else {
      ans = (ans + (qpow(2, c0) * (c1? qpow(2, c1 - 1) : 1) - 1 + kMod) % kMod * qpow(2, i)) % kMod;
    }
  }
  return ans;
}

void DFS(int x) {
  vector<int> s;
  if(x != 1) {
    s.push_back(arr[x]);
  }
  for(auto i : ch[x]) {
    DFS(i);
    s.push_back(arr[i]);
  }
  if(x != 1) {
    //cout << x << ' ' << cal(s, 0) << '\n';
    sum = (sum + cal(s, 0) * qpow(2, n - 1 - s.size())) % kMod;
  }else {
    //cout << x << ' ' << cal(s, arr[x], 1) << '\n';
    sum = (sum + cal(s, arr[x], 1) * qpow(2, n - 1 - s.size())) % kMod;
  }
}

signed main() {
  freopen("climb.in", "r", stdin);
  freopen("climb.out", "w", stdout);
  cin >> n;
  for(int i = 1; i <= n; i++) {
    cin >> arr[i];
  }
  for(int i = 2; i <= n; i++) {
    cin >> f;
    ch[f].push_back(i);
  }
  DFS(1);
  cout << sum << '\n';
  return 0;
}
//Off-Topic: It should be "crawl"

C 字符串

贪心,先贪断点的,然后贪连续的。

#include <bits/stdc++.h>
using namespace std;

int t, n, m, a, b, c, ans, cnt;

int main() {
  freopen("string.in", "r", stdin);
  freopen("string.out", "w", stdout);
  for(cin >> t; t--;) {
    cin >> n >> m >> a >> b >> c;
    ans = (n - 1) / a + (m - 1) / b + 2, cnt = min(n, m / c);
    for(int i = 1; i <= cnt; i++) {
      int val = 2 * i;
      if(c > b) {
        val += (c - 1) / b * i;
      }
      if(n - i > 0) {
        val += 1 + (n - i - 1) / a;
      }
      if(m - c * i > 0) {
        val++;
        int rst = m - c * i - 1;
        if(c <= b) {
          int nv = min(i, rst / (b + 1 - c));
          val += nv, rst -= nv * (b + 1 - c);
        }else {
          int nv = min(i, rst / (b - (c - 1) % b));
          val += nv, rst -= nv * (b - (c - 1) % b);
        }
        val += rst / b;
      }
      ans = max(ans, val);
    }
    cout << ans << '\n';
  }
  return 0;
}
posted @ 2024-10-03 16:17  hhc0001  阅读(17)  评论(0)    收藏  举报