《如 何 速 通 一 套 题》7.0

邮寄

开场半个小时秒了 B。

然后看 A,钻研了一个多小时吧,过了。

然后看 CD。结果 D 是大模拟,还是有文化的大模拟,直接使我停机,卡完了剩下两个小时,然后没分。

我爸让我沉下心来想一想,这就是后果,score-60

总共 200。

A 变幻

易得连续两个数不会一起操作。

所以就可以设 \(dp_{i, j}\) 表示考虑前 \(i\) 个,操作了 \(j\) 次的最大权值。

由于最后一个数不会被操作,转移易得:

\(a_{i + 1}\) 是山谷数时,\((i, j) \to (i + 2, j) + a_{i + 1}\)

否则:\((i, j) \to (i + 1, j), (i, j) \to (i + 2, j + 1) + (\min(a_i, a_{i + 2}) – 1)\)

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

int n, k, arr[2020], dp[2020][2020];

signed main() {
  freopen("change.in", "r", stdin);
  freopen("change.out", "w", stdout);
  cin >> n >> k;
  for(int i = 1; i <= n; i++) {
    cin >> arr[i];
  }
  memset(dp, 0x80, sizeof(dp));
  dp[0][0] = 0;
  for(int i = 0; i < n; i++) {
    for(int j = 0; j <= k; j++) {
      if(arr[i] > arr[i + 1] && arr[i + 2] > arr[i + 1]) {
        dp[i + 2][j] = max(dp[i + 2][j], dp[i][j] + arr[i + 1]);
      }else {
        dp[i + 1][j] = max(dp[i + 1][j], dp[i][j]);
        dp[i + 2][j + 1] = max(dp[i + 2][j + 1], dp[i][j] + (min(arr[i], arr[i + 2]) - 1));
      }
    }
  }
  int ans = 0x8080808080808080;
  for(int j = 0; j <= k; j++) {
    ans = max(ans, dp[n][j]);
  }
  cout << ans << '\n';
  return 0;
}

B 交替

结论题。

\(l = \lceil \frac{n}{2} \rceil – 1\)

\(n\) 是奇数,答案为 \(\sum \limits_{i = 0}^l (-1)^i \binom{l}{i} a_{2i}\)

否则,答案为 \(\sum \limits_{i = 0}^l (-1)^i \binom{l}{i} (a_{2i} + a_{2i + 1})\)

处理一下组合数直接算就行了。至于这个规律咋来的,我是手玩了 \(n\) 比较小的情况。

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

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

int n, arr[100010], fac[100010], inv[100010], rl, ans, val;

int qinv(int x) {
  int rs = 1;
  for(int tmp = kMod - 2; tmp; tmp >>= 1) {
    if(tmp & 1) {
      rs = 1ll * rs * x % kMod;
    }
    x = 1ll * x * x % kMod;
  }
  return rs;
}

void init() {
  fac[0] = 1;
  for(int i = 1; i <= 100000; i++) {
    fac[i] = 1ll * fac[i - 1] * i % kMod;
  }
  inv[100000] = qinv(fac[100000]);
  for(int i = 99999; i >= 0; i--) {
    inv[i] = 1ll * inv[i + 1] * (i + 1) % kMod;
  }
}

long long c(int x, int y) {
  if(x < 0 || y < 0 || x < y) {
    return 0;
  }
  return 1ll * fac[x] * inv[x - y] % kMod * inv[y] % kMod;
}

signed main() {
  freopen("alternate.in", "r", stdin);
  freopen("alternate.out", "w", stdout);
  init();
  cin >> n;
  for(int i = 0; i < n; i++) {
    cin >> arr[i];
  }
  rl = (n + 1) / 2 - 1, val = 1;
  if(n & 1) {
    for(int i = 0; i <= rl; i++) {
      ans = (ans + val * c(rl, i) * arr[i << 1] % kMod + kMod) % kMod;
      val = val * -1;
    }
  }else {
    for(int i = 0; i <= rl; i++) {
      ans = (ans + val * c(rl, i) * (arr[i << 1] + arr[(i << 1) | 1]) % kMod + kMod) % kMod;
      val = val * -1;
    }
  }
  cout << ans << '\n';
  return 0;
}

/*
auto [x, y, z] = ...
*/
请登录后发表评论

    没有回复内容