20241003

libohan0518發表於2024-10-03

縮排最佳化

我們可以列舉 \(i\) 的所有倍數,我們讓每一塊中的數除以 \(i\) 相等,顯然這是調和集數

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int N = 1e7 + 5, INF = 1e18;

int n, a[N], sum[N], ans = INF, cnt[N];

signed main() {
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
    sum[a[i]] += a[i];
    cnt[a[i]]++;
  }
  for (int i = 1; i <= 2000000; i++) {
    sum[i] += sum[i - 1];
    cnt[i] += cnt[i - 1];
  }
  for (int i = 1; i <= 1000000; i++) {
    int tmp = 0;
    for (int j = 0; j <= 1000000; j += i) {
      tmp += (sum[j + i - 1] - sum[max(0ll, j - 1)]) - (j * (cnt[j + i - 1] - cnt[max(0ll, j - 1)]));
      tmp += (j / i) * (cnt[j + i - 1] - cnt[max(0ll, j - 1)]);
    }
    ans = min(ans, tmp);
  }
  cout << ans;
  return 0;
}

外星人

首先如果 \(x \mod a = res\) 那麼 \(res \mod b (b >= a) = res\),所以我們可以直接將 \(a_i\) 送大到小排序,我們設 \(dp_{i, j}\) 表示當前選到了第 \(i\) 個數,當前的數字為 \(j\) ,那麼如果考慮當前這個數不選就是 \(dp_{i, j} += dp_{i - 1, j} \times (n - i)\) 因為當前這個數可以放到後面的 \(n - i\) 個位置 ,如果考慮當前這個數選,那麼就是 \(dp_{i, {j \mod a_i}} += dp_{i - 1, j}\)

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int N = 5e3 + 5, mod = 998244353;

int n, x, a[N], dp[N][N];

bool cmp(int _x, int _y) {
  return _x > _y;
}

signed main() {
  cin >> n >> x;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  sort(a + 1, a + n + 1, cmp);
  dp[0][x] = 1;
  for (int i = 1; i <= n; i++) {
    for (int j = 0; j <= x; j++) {
      dp[i][j % a[i]] += dp[i - 1][j];
      dp[i][j % a[i]] %= mod;
      dp[i][j] += (dp[i - 1][j] * (n - i) % mod);
      dp[i][j] %= mod;
    }
  }
  int ans = x;
  while (!dp[n][ans]) {
    ans--;
  }
  cout << ans << "\n" << dp[n][ans];
  return 0;
}

相關文章