topcoder srm 711 div1

problem1 link

如果$n$满足,答案就是$n$。否则,依次枚举连续1的位置判断即可。

problem2 link

给出一个整数$X=prod_{i=0}^{n-1}p_{i}^{a_{i}}$,其中$p_{i}$表示第i个素数,比如$p_{0}=2,p_{1}=3$。问有多少有序数列使得数列中每个数字大于1且所有数字的乘积等于$X$。当$X=6$时有三个,分别是{2,3},{3,2},{6}。其中$1leq n leq 50,1leq a_{i} leq 50$。

思路:令$f_{i}$表示将$X$表示成$i$个数乘积的方案数。那么$f_{i}=prod_{k=0}^{n-1}g(a_{k},i)-sum_{k=1}^{i-1}C_{i}^{k}f_{k}$。其中$g(i,j)$表示将$i$个苹果放在$j$个篮子里的方案数,$C_{i}^{j}$表示组合数。

那么答案$ans=sum f_{i}$

problem3 link

https://codeforces.com/blog/entry/50573

首先,枚舉第一個樹的邊,對後面每個樹,計算$dp[i][j]$,表示第$i$個樹選擇第$j$條邊的方案數.

code for problem1

#include <vector>

class ConsecutiveOnes {
 public:
  long long get(long long n, int k) {
    constexpr int N = 50;
    std::vector<int> a(N + 1);
    a[0] = 0;
    for (int i = 1; i <= N; ++i) {
      a[i] = (n >> (i - 1)) & 1;
      a[i] += a[i - 1];
    }
    for (int i = k; i <= N; ++i) {
      if (a[i] - a[i - k] == k) {
        return n;
      }
    }
    long long ans = ((n >> k) << k) | ((1ll << k) - 1);
    long long curr = ans;
    for (int i = k; i < N; ++i) {
      if (((curr >> (i - k)) & 1) == 1) {
        curr ^= 1ll << (i - k);
      }
      curr |= 1ll << i;
      if (curr >= n && curr < ans) {
        ans = curr;
      }
    }
    return ans;
  }
};

code for problem2

#include <vector>

constexpr int N = 3005;
constexpr int kMod = 1000000007;

class OrderedProduct {
 public:
  int count(const std::vector<int> &a) {
    int s = 0;
    int n = static_cast<int>(a.size());
    for (int i = 0; i < n; ++i) {
      s += a[i];
    }
    std::vector<long long> dp(s + 1, 0);
    long long ans = 0;
    for (int i = 1; i <= s; ++i) {
      dp[i] = 1;
      for (int j = 0; j < n; ++j) {
        dp[i] = dp[i] * Get(a[j] + i - 1, i - 1) % kMod;
      }
      for (int j = 1; j < i; ++j) {
        dp[i] -= Get(i, j) * dp[j] % kMod;
        if (dp[i] < 0) {
          dp[i] += kMod;
        }
      }
      ans += dp[i];
    }
    return static_cast<int>(ans % kMod);
  }

  OrderedProduct() : c(N, std::vector<int>(N)) {
    c[0][0] = 1;
    for (int i = 1; i < N; ++i) {
      c[i][0] = 1;
      for (int j = 1; j < N; ++j) {
        c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
        c[i][j] %= kMod;
      }
    }
  }

 private:
  int Get(int a, int b) {
    if (a < b) return 0;
    return c[a][b];
  }

  std::vector<std::vector<int>> c;
};

code for problem3

#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <vector>

static constexpr int kMod = 1000000007;

struct Tree {
  Tree(int root, int a, int b, int c, int n)
      : n(n),
        edges(n),
        father(n, std::vector<int>(10, -1)),
        depth(n),
        weight(n) {
    std::vector<int> x(n - 1);
    x[0] = c;
    for (int k = 1; k <= n - 2; ++k) {
      x[k] = (1ll * a * x[k - 1] + b) % kMod;
    }
    for (int j = 0; j <= n - 2; ++j) {
      int u = (root + j + 1) % n;
      int v = (root + (x[j] % (j + 1))) % n;
      if (u > v) {
        std::swap(u, v);
      }
      edges[u].emplace_back(v);
      edges[v].emplace_back(u);
    }
    Dfs(0, -1, 0);
    for (int i = 1; i < 10; ++i) {
      for (int j = 0; j < n; ++j) {
        int t = father[j][i - 1];
        if (t != -1) {
          father[j][i] = father[t][i - 1];
        }
      }
    }
  }

  int Lca(int u, int v) {
    int key = std::min(u, v) * n + std::max(u, v);
    {
      auto iter = lca_cache.find(key);
      if (iter != lca_cache.end()) {
        return iter->second;
      }
    }
    if (depth[u] > depth[v]) {
      std::swap(u, v);
    }
    for (int i = 9; i >= 0; --i) {
      if (depth[v] == depth[u]) {
        break;
      }
      int t = father[v][i];
      if (t == -1) {
        continue;
      }
      if (depth[t] >= depth[u]) {
        v = t;
      }
    }
    if (depth[v] != depth[u]) {
      v = father[v][0];
    }
    if (u == v) {
      lca_cache.emplace(key, u);
      return u;
    }

    for (int i = 9; i >= 0; --i) {
      int pu = father[u][i];
      int pv = father[v][i];
      if (pu == -1 || pu == pv) {
        continue;
      }
      u = pu;
      v = pv;
    }
    if (u != v) {
      u = father[u][0];
      v = father[v][0];
    }
    lca_cache.emplace(key, u);
    return u;
  }

  void Dfs(int u, int p, int d) {
    depth[u] = d;
    for (int x : edges[u]) {
      if (x != p) {
        father[x][0] = u;
        Dfs(x, u, d + 1);
      }
    }
  }

  void Clear() {
    for (int i = 0; i < n; ++i) {
      weight[i] = 0;
    }
  }

  void Add(int u, int v, int w) {
    int c = Lca(u, v);
    if (c == v) {
      weight[u] = Add(weight[u], w);
      weight[c] = Sub(weight[c], w);
    } else if (c == u) {
      weight[v] = Add(weight[v], w);
      weight[c] = Sub(weight[c], w);
    } else {
      weight[v] = Add(weight[v], w);
      weight[u] = Add(weight[u], w);
      weight[c] = Sub(weight[c], Add(w, w));
    }
  }

  void Compute(int u = 0, int p = -1) {
    for (int x : edges[u]) {
      if (x != p) {
        Compute(x, u);
        weight[u] = Add(weight[u], weight[x]);
      }
    }
  }

  void Sons(int u, int p, std::unordered_set<int> *son) {
    son->emplace(u);
    for (int x : edges[u]) {
      if (x != p) {
        Sons(x, u, son);
      }
    }
  }

  int Add(int x, int y) {
    x += y;
    if (x >= kMod) {
      x -= kMod;
    }
    return x;
  }

  int Sub(int x, int y) {
    x -= y;
    if (x < 0) {
      x += kMod;
    }
    return x;
  }

  int n;
  std::vector<std::vector<int>> edges;
  std::vector<std::vector<int>> father;
  std::vector<int> depth;
  std::unordered_map<int, int> lca_cache;
  std::vector<int> weight;
};

class TreeMoving {
 public:
  int count(int n, const std::vector<int> &roots, const std::vector<int> &a,
            const std::vector<int> &b, const std::vector<int> &c) {
    int m = static_cast<int>(roots.size());
    std::vector<Tree> trees;
    for (int i = 0; i < m; ++i) {
      trees.emplace_back(roots[i], a[i], b[i], c[i], n);
    }
    int result = 0;
    for (int u = 1; u < n; ++u) {
      int v = trees[0].father[u][0];
      trees[0].weight[u] = 1;
      for (int i = 1; i < m; ++i) {
        trees[i].Clear();
        for (int cu = 1; cu < n; ++cu) {
          int cv = trees[i - 1].father[cu][0];
          trees[i].Add(cu, cv, trees[i - 1].weight[cu]);
        }
        trees[i].Compute();
      }
      std::unordered_set<int> sons;
      trees[0].Sons(u, v, &sons);
      for (int cu = 1; cu < n; ++cu) {
        int cv = trees[m - 1].father[cu][0];
        if (sons.count(cu) + sons.count(cv) == 1) {
          result += trees[m - 1].weight[cu];
          result %= kMod;
        }
      }
      trees[0].weight[u] = 0;
    }
    return result;
  }
};
原文地址:https://www.cnblogs.com/jianglangcaijin/p/6632050.html