BJ United Round #2 简要题解

序列

转差分,左右来回构造一个回路。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>

#include <algorithm>
#include <bitset>
#include <queue>
#include <functional>
#include <set>
#include <map>
#include <vector>
#include <iostream>
#include <limits>
#include <numeric>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int N = 300010;

int t;
ll a[N];

int main() {
#ifdef LBT
  freopen("test.in", "r", stdin);
  int nol_cl = clock();
#endif

  scanf("%d", &t);
  while (t--) {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
      scanf("%lld", &a[i]);
    a[0] = 0;
    for (int i = 1; i <= n; ++i)
      a[i] += a[i - 1];
    ll lst = a[n];
    sort(a, a + n + 1);
    ll ans = 0;
    int pos1 = lower_bound(a, a + n + 1, 0LL) - a, pos2 = lower_bound(a, a + n + 1, lst) - a;
    if (pos1 == pos2) ++pos2;
    if (pos1 > pos2) swap(pos1, pos2);
    if (pos1) {
      ans = a[1] - a[0];
      for (int i = 0; i + 2 <= pos1; ++i)
        ans = max(ans, a[i + 2] - a[i]);
    }
    if (pos2 < n) {
      ans = max(ans, a[n] - a[n - 1]);
      for (int i = pos2; i + 2 <= n; ++i)
        ans = max(ans, a[i + 2] - a[i]);
    }
    if (pos2 - pos1 == 1) {
      if (pos1 && pos2 < n) ans = max(ans, a[pos2 + 1] - a[pos1 - 1]);
      else {
        if (pos1) ans = max(ans, a[pos2] - a[pos1 - 1]);
        if (pos2 < n) ans = max(ans, a[pos2 + 1] - a[pos1]);
      }
    } else {
      for (int i = pos1 + 1; i + 1 < pos2; ++i)
        ans = max(ans, a[i + 1] - a[i]);
      if (pos1) ans = max(ans, a[pos1 + 1] - a[pos1 - 1]);
      else ans = max(ans, a[pos1 + 1] - a[pos1]);
      if (pos2 < n) ans = max(ans, a[pos2 + 1] - a[pos2 - 1]);
      else ans = max(ans, a[pos2] - a[pos2 - 1]);
    }
    printf("%lld\n", ans);
  }

#ifdef LBT
  LOG("Time: %dms\n", int ((clock()
          -nol_cl) / (double)CLOCKS_PER_SEC * 1000));
#endif
  return 0;
}

随机

二分答案,然后发现可以根据最终结果是否变化来判断。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>

#include <algorithm>
#include <bitset>
#include <queue>
#include <functional>
#include <set>
#include <map>
#include <vector>
#include <iostream>
#include <limits>
#include <numeric>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

struct E {
  int v, w, x;
  E* next;
};

const int N = 110, M = 210, W = 110;

int n, L;
int xs[N];
double dp[N][N * W];
bool vis[N];
E* g[N];

void adde(int u, int v, int w, int x) {
  static E pool[M], *p = pool;
  p->v = v;
  p->w = w;
  p->x = x;
  p->next = g[u];
  xs[u] += x;
  g[u] = p;
  ++p;
}

double guess;

void dfs(int u) {
  if (vis[u])
    return;
  vis[u] = true;
  if (!xs[u])
    return;
  memset(dp[u], 0, sizeof(dp[u]));
  for (E* p = g[u]; p; p = p->next) {
    dfs(p->v);
    for (int i = 0; i <= L - p->w; ++i)
      dp[u][i] += (p->w + dp[p->v][p->w + i]) * p->x;
    for (int i = L - p->w + 1; i <= L; ++i)
      dp[u][i] += (p->w + guess) * p->x;
  }
  for (int i = 0; i <= L; ++i)
    dp[u][i] = min(dp[u][i] / xs[u], u == 1 ? 1e9 : guess);
}

double check(double x) {
  memset(vis, 0, sizeof(vis));
  guess = x;
  dfs(1);
  return dp[1][0];
}

int main() {
#ifdef LBT
  freopen("test.in", "r", stdin);
  int nol_cl = clock();
#endif

  int m;
  scanf("%d%d%d", &n, &m, &L);
  L = min(L, (n - 1) * 100);
  while (m--) {
    int u, v, w, x;
    scanf("%d%d%d%d", &u, &v, &w, &x);
    adde(u, v, w, x);
  }
  double l = 0, r = 1e9;
  while ((r - l) / max(1.0, l) > 8e-10) {
    double mid = (l + r) / 2;
    double val = check(mid);
    if (val < mid)
      r = val;
    else
      l = val;
  }
  printf("%.10f\n", l);

#ifdef LBT
  LOG("Time: %dms\n", int ((clock()
          -nol_cl) / (double)CLOCKS_PER_SEC * 1000));
#endif
  return 0;
}

计数

裸的 Burnside

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>

#include <algorithm>
#include <bitset>
#include <queue>
#include <functional>
#include <set>
#include <map>
#include <vector>
#include <iostream>
#include <limits>
#include <numeric>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int P = 998244353;

const int N = 52;

int n, w1, w2, w3, ans;
int fac[N], ifac[N], inv[N], cnt[N], arr[N];
int lcmTable[N][N][N];
int powTable[3][N * N * N];

int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }

int lcm(int a, int b) { return a / gcd(a, b) * b; }

int norm(int x) { return x >= P ? x - P : x; }

void add(int& x, int y) {
  if ((x += y) >= P) x -= P;
}

void sub(int& x, int y) {
  if ((x -= y) < 0) x += P;
}

int mpow(int x, int k) {
  int ret = 1;
  while (k) {
    if (k & 1)
      ret = ret * (ll)x % P;
    x = x * (ll)x % P;
    k >>= 1;
  }
  return ret;
}

void dfs(int sum, int curMax, int curCon, int k) {
  if (sum == 0) {
    add(ans, curCon);
    return;
  }
  for (int i = 1; i <= curMax; ++i) {
    int tmp = curCon * (ll)inv[i] % P * inv[++cnt[i]] % P;
    arr[k] = i;
    tmp = tmp * (ll)w1 % P;
    int d2 = i - 1, d3 = (i - 1) * i;
    for (int j = 0; j < k; ++j) {
      int g = i * arr[j] / lcmTable[i][arr[j]][1];
      d2 += g * 2;
      d3 += g * (i * 3 + arr[j] * 3 - 2);
      for (int l = 0; l < j; ++l)
        d3 += i * arr[j] * arr[l] / lcmTable[i][arr[j]][arr[l]] * 6;
    }
    tmp = tmp * (ll)powTable[1][d2] % P * powTable[2][d3] % P;
    dfs(sum - i, min(sum - i, i), tmp, k + 1);
    --cnt[i];
  }
}

int main() {
#ifdef LBT
  freopen("test.in", "r", stdin);
  int nol_cl = clock();
#endif

  scanf("%d%d%d%d", &n, &w1, &w2, &w3);
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j)
      for (int k = 1; k <= n; ++k)
        lcmTable[i][j][k] = lcm(lcm(i, j), k);
  powTable[0][1] = w1;
  powTable[1][1] = w2;
  powTable[2][1] = w3;
  for (int i = 0; i < 3; ++i) {
    powTable[i][0] = 1;
    for (int j = 2; j <= n * n * n; ++j)
      powTable[i][j] = powTable[i][j - 1] * (ll) powTable[i][1] % P;
  }
  fac[0] = 1;
  for (int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * (ll)i % P;
  inv[1] = 1;
  for (int i = 2; i <= n; ++i) inv[i] = -(P / i) * (ll)inv[P % i] % P + P;
  ifac[0] = 1;
  for (int i = 1; i <= n; ++i) ifac[i] = ifac[i - 1] * (ll)inv[i] % P;
  dfs(n, n, 1, 0);
  printf("%d\n", ans);

#ifdef LBT
  LOG("Time: %dms\n", int ((clock()
          -nol_cl) / (double)CLOCKS_PER_SEC * 1000));
#endif
  return 0;
}

猜你喜欢

转载自blog.csdn.net/EI_Captain/article/details/101599092
bj