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}。其中$1\leq n \leq 50,1\leq 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;
}
};