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;
    }
    
  • 相关阅读:
    二分查找 找到了返回位置 没找到返回应该插入的位置
    前端知识结构
    RequireJS
    Java内部类——成员内部类
    Java笔记
    Java单例模式
    Java与C#的语法区别(不断更新中...)
    进制转换
    查找算法——折半查找
    排序算法——冒泡排序
  • 原文地址:https://www.cnblogs.com/cycleke/p/11523857.html
Copyright © 2011-2022 走看看