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; } };