zoukankan      html  css  js  c++  java
  • 2016 ICPC 沈阳

    A.Thickest Burger

    签到题,输出(max(a+2b,2a+b))

    void solve() {
      int a, b;
      cin >> a >> b;
      cout << max(a + 2 * b, 2 * a + b) << '
    ';
    }
    
    int main(int argc, char *argv[]) {
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      cout << fixed << setprecision(10);
    
      int o_o;
      for (cin >> o_o; o_o; --o_o) solve();
    
      return 0;
    }
    

    B.Relative atomic mass

    签到题,计算分子量。

    void solve() {
      string s;
      cin >> s;
      int ans = 0;
      for (char &ch : s) {
        if (ch == 'C') {
          ans += 12;
        } else if (ch == 'H') {
          ++ans;
        } else {
          ans += 16;
        }
      }
      cout << ans << '
    ';
    }
    
    int main(int argc, char *argv[]) {
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      cout << fixed << setprecision(10);
    
      int o_o;
      for (cin >> o_o; o_o; --o_o) solve();
    
      return 0;
    }
    

    C.Recursive sequence

    矩阵快速幂经典题
    $ f_n = f_{n - 1} + 2 f_{n - 2} + n^4 $

    const int MAXN = 7;
    const ull MOD = 2147493647;
    
    typedef ull Mat[MAXN][MAXN];
    
    void mul(Mat &a, const Mat &b) {
      static Mat c;
      ZERO(c);
      FOR2(i, 0, MAXN, j, 0, MAXN)
      FOR(k, 0, MAXN) c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % MOD;
      memcpy(a, c, sizeof(c));
    }
    
    Mat A, B;
    
    const Mat P = {{1, 2, 1, 4, 6, 4, 1}, {1, 0, 0, 0, 0, 0, 0},
                   {0, 0, 1, 4, 6, 4, 1}, {0, 0, 0, 1, 3, 3, 1},
                   {0, 0, 0, 0, 1, 2, 1}, {0, 0, 0, 0, 0, 1, 1},
                   {0, 0, 0, 0, 0, 0, 1}};
    
    void solve() {
      int n, a, b;
      cin >> n >> a >> b;
      if (n < 3) {
        cout << (n == 1 ? a : b) << '
    ';
        return;
      }
      ZERO(A);
      MEMCPY(B, P, sizeof(P));
      FOR(i, 0, MAXN) A[i][i] = 1;
      for (n -= 2; n; n >>= 1, mul(B, B))
        if (n & 1) mul(A, B);
      ull ans = 0;
      const ull L[] = {1ULL * b, 1ULL * a, 16, 8, 4, 2, 1};
      FOR(i, 0, MAXN) ans = (ans + A[0][i] * L[i]) % MOD;
      cout << ans << '
    ';
    }
    
    int main(int argc, char *argv[]) {
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      cout << fixed << setprecision(10);
    
      int o_o;
      for (cin >> o_o; o_o; --o_o) solve();
    
      return 0;
    }
    

    E.Counting Cliques

    题意:计算一个图中大小为S的完全子图的个数,每个点的度不超过20。

    因为每个点的度很小,所以可以暴力dfs。

    const int MAXN = 100 + 3;
    
    vi adj[MAXN];
    bool connected[MAXN][MAXN], vis[MAXN];
    int n, m, s, top, stk[MAXN], ans;
    
    inline bool check(int u) {
      FOR(i, 0, top)
        if (!connected[stk[i]][u]) return false;
      return true;
    }
    
    void dfs(int u) {
      if (top == s) return (void)(++ans);
      if (n - u + top < s) return;
      FOR(i, 0, adj[u].size()) {
        if (vis[adj[u][i]] || !check(adj[u][i])) continue;
        vis[adj[u][i]] = true;
        stk[top++] = adj[u][i];
        dfs(adj[u][i]);
        --top;
        vis[adj[u][i]] = false;
      }
    }
    
    void solve() {
      cin >> n >> m >> s;
      FOR(i, 0, n) adj[i].clear(), vis[i] = false;
      FOR2(i, 0, n, j, 0, n) connected[i][j] = false;
      for (int u, v; m; --m) {
        cin >> u >> v;
        if (--u > --v) swap(u, v);
        adj[u].push_back(v);
        connected[u][v] = true;
      }
      ans = 0;
      FOR(i, 0, n) {
        top = 1;
        stk[0] = i;
        vis[i] = true;
        dfs(i);
      }
      cout << ans << '
    ';
    }
    
    int main(int argc, char *argv[]) {
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      cout << fixed << setprecision(10);
    
      int o_o;
      for (cin >> o_o; o_o; --o_o) solve();
    
      return 0;
    }
    

    G.Do not pour out

    题意:给你一个杯子,直径为2,高为2,水高为d,现将杯子倾斜,使得水恰好不洒出,问
    此时水表面面积。

    显然表面为椭圆或半椭圆,分为两种情况:

    1. 水面经过杯底,通过二分得出水在杯底的面积,然后计算。
    2. 水面越过杯底,可以较轻松的算出长短半轴。
    #include <bits/stdc++.h>
    using namespace std;
    
    const double EPS = 1e-12;
    const double PI = acos(-1.0);
    
    inline double cal_v(double x) {
      double t = acos(1 - x);
      double v = sin(t) - sin(t) * sin(t) * sin(t) / 3 - t * cos(t);
      return v * 2 / x;
    }
    
    inline double ract(double a, double x) { return (x + sin(2 * x) / 2) * a / 2; }
    
    inline double area(double a, double x) {
      return 2 * (ract(a, PI / 2) - ract(a, asin(x / a)));
    }
    
    void solve() {
      double d;
      cin >> d;
      if (d == 0) {
        cout << .0 << '
    ';
        return;
      }
      if (d > 1) {
        double h = 2 * d - 2;
        double a = sqrt(4 + (2 - h) * (2 - h)) / 2;
        cout << PI * a << '
    ';
        return;
      }
      double l = 0, r = 2, v = PI * d;
      for (int step = 0; step < 100; ++step) {
        double mid = (l + r) / 2;
        if (cal_v(mid) > v + EPS) {
          r = mid;
        } else {
          l = mid;
        }
      }
      int sign = l < 1 ? -1 : 1;
      double len = sqrt(l * l + 4);
      double h = sqrt(2 * l - l * l);
      double a = len / (1 + sign * sqrt(1 - h * h));
      double x = a - len;
      cout << area(a, x) << '
    ';
    }
    
    int main() {
      ios::sync_with_stdio(false);
      cin.tie(0);
      cout << fixed << setprecision(5);
    
      int o_o;
      for (cin >> o_o; o_o; --o_o) solve();
      return 0;
    }
    

    H.Guessing the Dice Roll

    题意:一群人在完骰子游戏,每个人有一个特定的序列,当掷到这个序列时对应的人获胜,
    问每个人获胜的概率。

    在AC自动机上做概率dp,由于AC自动机不是一个DAG所以要用高斯消元求解。

    const int MAX_NODE = 103;
    
    int ch[MAX_NODE][6], fail[MAX_NODE], node_c;
    
    int add_char(int u, int id) {
      if (ch[u][id] < 0) ch[u][id] = node_c++;
      return ch[u][id];
    }
    
    void build_acam() {
      queue<int> que;
      FOR(i, 0, 6)
      if (~ch[0][i]) {
        que.push(ch[0][i]);
        fail[ch[0][i]] = 0;
      } else {
        ch[0][i] = 0;
      }
      while (!que.empty()) {
        int u = que.front();
        que.pop();
        FOR(i, 0, 6)
        if (~ch[u][i]) {
          que.push(ch[u][i]);
          fail[ch[u][i]] = ch[fail[u]][i];
        } else {
          ch[u][i] = ch[fail[u]][i];
        }
      }
    }
    
    const double EPS = 1e-9;
    const int MAXN = MAX_NODE;
    double a[MAXN][MAXN], x[MAXN];
    int equ, var;
    
    int gauss() {
      int i, j, k, col, max_r;
      for (k = 0, col = 0; k < equ && col < var; k++, col++) {
        max_r = k;
        for (i = k + 1; i < equ; i++)
          if (fabs(a[i][col]) > fabs(a[max_r][col])) max_r = i;
        if (fabs(a[max_r][col]) < EPS) return 0;
    
        if (k != max_r) {
          for (j = col; j < var; j++) swap(a[k][j], a[max_r][j]);
          swap(x[k], x[max_r]);
        }
    
        x[k] /= a[k][col];
        for (j = col + 1; j < var; j++) a[k][j] /= a[k][col];
        a[k][col] = 1;
    
        for (i = k + 1; i < equ; i++)
          if (i != k) {
            x[i] -= x[k] * a[i][col];
            for (j = col + 1; j < var; j++) a[i][j] -= a[k][j] * a[i][col];
            a[i][col] = 0;
          }
      }
    
      for (col = equ - 1, k = var - 1; ~col; --col, --k) {
        if (fabs(a[col][k]) > 0) {
          for (i = 0; i < k; ++i) {
            x[i] -= x[k] * a[i][col];
            for (j = col + 1; j < var; j++) a[i][j] -= a[k][j] * a[i][col];
            a[i][col] = 0;
          }
        }
      }
    
      return 1;
    }
    
    int ed_node[10], id[MAXN];
    
    void solve() {
      int n, l, t;
      cin >> n >> l;
    
      node_c = 1;
      memset(ch, -1, sizeof(ch));
      memset(id, -1, sizeof(id));
      FOR(i, 0, n) {
        ed_node[i] = 0;
        FOR(j, 0, l) cin >> t, ed_node[i] = add_char(ed_node[i], t - 1);
        id[ed_node[i]] = i;
      }
      build_acam();
    
      FOR(step, 0, n) {
        equ = var = node_c;
        FOR(i, 0, equ) {
          x[i] = 0;
          FOR(j, 0, var) a[i][j] = 0;
        }
        FOR(i, 0, node_c) {
          a[i][i] = 1;
          if (~id[i]) {
            x[i] = id[i] == step ? 1 : 0;
          } else {
            FOR(j, 0, 6) a[i][ch[i][j]] += -1.0 / 6;
          }
        }
    
        /*
        FOR(i, 0, node_c) {
          FOR(j, 0, var) cout << a[i][j] << ' ';
          cout << x[i] << '
    ';
        }
        */
    
        gauss();
        if (step) cout << ' ';
        cout << x[0];
      }
      cout << '
    ';
    }
    
    int main(int argc, char *argv[]) {
      // freopen("in.txt", "r", stdin);
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      cout << fixed << setprecision(6);
    
      int o_o;
      for (cin >> o_o; o_o; --o_o) solve();
    
      return 0;
    }
    

    I.The Elder

    题意:给定一棵带边权树,根节点为1,每个节点要想给根节点通过记者传递信息。记者经
    一段路耗时为长度的平方。记者间也可以传递信息,耗时为P,问在最优方案下,一个信息
    传递到根节点最长耗时。

    定义$ dp_i $ 表示i节点传递到根节点的最短耗时,规定$ dp_{root}=-P (。有如下转移方程 ) dp_u = dp_v + dist(u, v)^2 + P$,v is an ancestor of u.

    然后就是在树上做斜率优化。

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    typedef pair<int, int> pii;
    const int MAXN = 1e5 + 5;
    
    vector<pii> adj[MAXN];
    ll dp[MAXN], d[MAXN];
    int n, p, q[MAXN], head, tail;
    
    inline ll S(int a, int b) { return (d[b] - d[a]) << 1; }
    inline ll G(int a, int b) { return dp[b] - dp[a] + d[b] * d[b] - d[a] * d[a]; }
    
    void dfs(int u, int from) {
      vector<int> dhead, dtail;
      if (u ^ 1) {
        while (head + 2 <= tail &&
               S(q[head + 1], q[head]) * d[u] <= G(q[head + 1], q[head]))
          dhead.push_back(q[head++]);
        int v = q[head];
        dp[u] = dp[v] + p + (d[u] - d[v]) * (d[u] - d[v]);
      }
      while (head + 2 <= tail &&
             G(u, q[tail - 1]) * S(q[tail - 1], q[tail - 2]) <=
                 G(q[tail - 1], q[tail - 2]) * S(u, q[tail - 1]))
        dtail.push_back(q[--tail]);
      q[tail++] = u;
      for (pii &e : adj[u]) {
        if (e.first == from) continue;
        d[e.first] = d[u] + e.second;
        dfs(e.first, u);
      }
      --tail;
      for (int i = dtail.size() - 1; ~i; --i) q[tail++] = dtail[i];
      for (int i = dhead.size() - 1; ~i; --i) q[--head] = dhead[i];
    }
    
    void solve() {
      cin >> n >> p;
      for (int i = 1; i <= n; ++i) adj[i].clear();
      for (int i = 1, u, v, w; i < n; ++i) {
        cin >> u >> v >> w;
        adj[u].emplace_back(v, w);
        adj[v].emplace_back(u, w);
      }
      dp[1] = -p;
      head = tail = 0;
      dfs(1, 1);
    
      ll ans = 0;
      for (int i = 1; i <= n; ++i)
        if (dp[i] > ans) ans = dp[i];
      cout << ans << '
    ';
    }
    
    int main() {
      // freopen("in.txt", "r", stdin);
      ios::sync_with_stdio(false);
      cin.tie(0);
    
      int o_o;
      for (cin >> o_o; o_o; --o_o) solve();
    
      return 0;
    }
    
  • 相关阅读:
    D. Babaei and Birthday Cake--- Codeforces Round #343 (Div. 2)
    Vijos P1389婚礼上的小杉
    AIM Tech Round (Div. 2) C. Graph and String
    HDU 5627Clarke and MST
    bzoj 3332 旧试题
    codeforces 842C Ilya And The Tree
    codesforces 671D Roads in Yusland
    Travelling
    codeforces 606C Sorting Railway Cars
    codeforces 651C Watchmen
  • 原文地址:https://www.cnblogs.com/cycleke/p/11523857.html
Copyright © 2011-2022 走看看