# ZJOI2018 Day1 简要题解

### line

• ${V}_{L\left(G\right)}={E}_{G}$$V_{L(G)} = E_G$

• ${V}_{{L}^{2}\left(G\right)}=\sum \frac{{d}_{i}\left({d}_{i}-1\right)}{2}$$V_{L^2(G)} = \sum \frac{d_i(d_i-1)}{2}$

• ${V}_{{L}^{3}\left(G\right)}=\sum \frac{{d}_{i}\left({d}_{i}-1\right)\left({d}_{i}-2\right)}{2}+\sum _{e}\left({d}_{u}-1\right)\left({d}_{v}-1\right)$$V_{L^3(G)} = \sum \frac{d_i(d_i-1)(d_i-2)}{2} + \sum_e (d_u-1)(d_v-1)$

• ${V}_{{L}^{4}\left(G\right)}={V}_{{L}^{3}\left(L\left(G\right)\right)}$$V_{L^4(G)} = V_{L^3(L(G))}$ ，考虑计算 $L\left(G\right)$$L(G)$ 的每个点的度数，不难发现对于 $G$$G$ 的一条边 $\left(u,v\right)$$(u, v)$ ，它在 $L\left(G\right)$$L(G)$ 中度数为 ${d}_{u}+{d}_{v}-2$$d_u + d_v - 2$ ，而在 $L\left(G\right)$$L(G)$ 中的一条边表示有公共点的一对边，枚举公共点，需要算 $\sum _{u$\sum_{u ，这个可以通过计算和的平方以及平方的和来计算。

• 其他情况暴力求出 ${L}^{k-4}\left(G\right)$$L^{k-4}(G)$

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 5005;
const int M = 1000005;
const int mod = 998244353;

struct Tree {
int n, val, slf, lef;
} tre[N];

struct Graph {
vector <pii> E;
int V;
} G;

int n, m, all, ans, cur, rot, slf, tot, fac[N], siz[N], bin[N][15], f[N][N];
unordered_map <int, int> ind, sam;
vector <string> sub;
bool seq[N];

inline int Qow(int x, int y) {
int r = 1;
for (; y; y >>= 1, x = 1LL * x * x % mod) {
if (y & 1) {
r = 1LL * r * x % mod;
}
}
return r;
}

inline int FindTree() {
int x = ++tot;
++cur;
return x;
}

inline string FindHash(int x, int p) {
vector <string> chd;
string ret = "1";
for (auto y : adj[x]) {
if (y != p) {
chd.pb(FindHash(y, x));
}
}
sort(chd.begin(), chd.end());
for (int i = 0, j = 0; i < chd.size(); ) {
for (; j < chd.size() && chd[j] == chd[i]; ++j);
slf = 1LL * slf * fac[j - i] % mod;
for (; i < j; ret += chd[i], ++i);
}
if (x == 1) {
sub = chd;
}
return ret + "0";
}

inline int ToInt(string s) {
int ret = 0;
for (int i = 0; i < s.length(); ++i) {
ret = ret << 1 | s[i] - '0';
}
return ret;
}

inline Graph L(Graph G) {
Graph H;
H.V = G.E.size();
for (int i = 0; i < G.V; ++i) {
}
for (int i = 0; i < G.E.size(); ++i) {
}
for (int i = 0; i < G.V; ++i) {
for (int j = 0; j < adj[i].size(); ++j) {
for (int k = 0; k < j; ++k) {
}
}
}
return H;
}

inline void FindSize(int x, int p) {
siz[x] = 1;
for (auto y : adj[x]) {
if (y != p) {
FindSize(y, x), siz[x] += siz[y];
}
}
}

inline void FindRoot(int x, int p, int n) {
siz[x] = n - siz[x];
for (auto y : adj[x]) {
if (y != p) {
CheckMax(siz[x], siz[y]), FindRoot(y, x, n);
}
}
if (!rot || siz[rot] > siz[x]) {
rot = x;
}
}

inline string FindSubtree(int x, int p, int s) {
vector <string> chd;
string ret = "1";
for (auto y : adj[x]) {
if (y != p && (s >> y - 1 & 1)) {
chd.pb(FindSubtree(y, x, s));
}
}
sort(chd.begin(), chd.end());
for (auto s : chd) {
ret += s;
}
return ret + "0";
}

inline void Solve(int n) {
for (int i = 1; i <= n; ++i) {
}
tot = 0, cur = slf = 1, sub.clear(), FindTree();
string hsh = FindHash(1, 0);
if (ind[ToInt(hsh)]) {
return ;
}
int x = ind[ToInt(hsh)] = ++all;
tre[x].n = n, tre[x].slf = slf;
for (auto s : sub) {
if (s == "10") {
++tre[x].lef;
} else {
}
}
for (int i = 1; i <= n; ++i) {
for (auto j : adj[i]) {
if (j > i) {
}
}
}
rot = 0, FindSize(1, 0), FindRoot(1, 0, n);
sub.clear(), hsh = FindHash(rot, 0);
if (sam[ToInt(hsh)]) {
tre[x].val = tre[sam[ToInt(hsh)]].val;
return ;
}
sam[ToInt(hsh)] = x;
G.V = n, G.E.clear();
for (int i = 1; i <= n; ++i) {
for (auto j : adj[i]) {
if (i < j) {
G.E.pb(mp(i - 1, j - 1));
}
}
}
if (m >= 4) {
for (int i = 1; i <= m - 4; ++i) {
G = L(G);
}
int ret = 0, n = G.V, m = G.E.size();
vector <int> d(n, 0), e(m, 0);
for (int i = 0; i < n; ++i) {
val[i].clear();
}
for (int i = 0; i < m; ++i) {
++d[G.E[i].X], ++d[G.E[i].Y];
}
for (int i = 0; i < m; ++i) {
e[i] = d[G.E[i].X] + d[G.E[i].Y] - 2;
ret = (1LL * e[i] * (e[i] - 1) % mod * (e[i] - 2) % mod * (mod + 1) / 2 + ret) % mod;
val[G.E[i].X].pb(e[i] - 1), val[G.E[i].Y].pb(e[i] - 1);
}
for (int i = 0; i < n; ++i) {
if (val[i].size() > 1) {
int sum = 0, sqr = 0;
for (int j = 0; j < val[i].size(); ++j) {
sum = (sum + val[i][j]) % mod, sqr = (1LL * val[i][j] * val[i][j] + sqr) % mod;
}
sum = 1LL * sum * sum % mod;
ret = (1LL * (sum - sqr + mod) * (mod + 1) / 2 + ret) % mod;
}
}
tre[x].val = ret;
} else {
for (int i = 1; i <= m; ++i) {
G = L(G);
}
tre[x].val = G.V;
}
for (int i = 1; i < (1 << n) - 1; ++i) {
int t = 0;
for (int j = 0; j < n; ++j) {
if (i >> j & 1) {
t = j + 1;
break;
}
}
string s = FindSubtree(t, 0, i);
if (s.length() == __builtin_popcount(i) << 1) {
tre[x].val = (tre[x].val - tre[ind[ToInt(s)]].val + mod) % mod;
}
}
}

inline void DFS(int x, int d, int c, int n) {
if (x == n << 1) {
Solve(n);
} else {
if (d) {
seq[x] = false, DFS(x + 1, d - 1, c, n);
}
if (c < n) {
seq[x] = true, DFS(x + 1, d + 1, c + 1, n);
}
}
}

inline void FindAllTree(int n) {
seq[1] = true, seq[n << 1] = false, DFS(2, 0, 1, n);
}

inline int DP(vector <int> a, vector <int> b, int c) {
static int g[N];
int n = a.size(), m = b.size();
if (n < m + c) {
return 0;
}
for (int i = 0; i < 1 << m; ++i) {
g[i] = 0;
}
g[0] = 1;
for (auto x : a) {
for (int i = (1 << m) - 1; ~i; --i) {
for (int j = 0; j < m; ++j) {
if (!(i >> j & 1)) {
g[i | 1 << j] = (1LL * f[x][b[j]] * g[i] + g[i | 1 << j]) % mod;
}
}
}
}
return 1LL * g[(1 << m) - 1] * bin[n - m][c] % mod * fac[c] % mod;
}

inline void DP(int x, int p) {
vector <int> chd;
for (auto y : adj[x]) {
if (y != p) {
DP(y, x), chd.pb(y);
}
}
for (int i = 1; i <= all; ++i) {
}
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
for (int i = 1; i <= m + 1; ++i) {
FindAllTree(i), fac[i] = 1LL * fac[i - 1] * i % mod;
}
for (int i = 1; i <= n; ++i) {
}
for (int i = 1, x, y; i < n; ++i) {
}
for (int i = 0; i <= n; ++i) {
bin[i][0] = 1;
for (int j = 1; j <= m && j <= i; ++j) {
bin[i][j] = (bin[i - 1][j] + bin[i - 1][j - 1]) % mod;
}
}
DP(1, 0);
for (int i = 1; i <= all; ++i) {
tre[i].val = 1LL * tre[i].val * Qow(tre[i].slf, mod - 2) % mod;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= all; ++j) {
ans = (1LL * f[i][j] * tre[j].val + ans) % mod;
}
}
printf("%d\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}

### history

$2si{z}_{i}>si{z}_{pa{r}_{i}}$$2siz_i > siz_{par_i}$$i$$i$ 认为是 $\mathtt{\text{LCT}}$$\texttt{LCT}$$pa{r}_{i}$$par_i$$\mathtt{\text{preferred child}}$$\texttt{preferred child}$ ，那么不难发现轻边个数是 $O\left(\mathrm{log}\sum {a}_{i}\right)$$O(\log \sum a_i)$ 条的，所以类似 $\mathtt{\text{LCT}}$$\texttt{LCT}$ 暴力维护即可。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 400005;

int n, m, f[N], par[N], siz[N], chd[N][2];
LL ans, a[N], tag[N], sum[N];

inline void DFS(int x) {
LL max_sum = sum[x] = a[x];
int pos = x;
for (int i = 0; i < adj[x].size(); ++i) {
if (y != par[x]) {
par[y] = f[y] = x, DFS(y), sum[x] += sum[y];
if (CheckMax(max_sum, sum[y])) {
pos = y;
}
}
}
if (max_sum << 1 > sum[x]) {
ans += sum[x] - max_sum << 1;
if (pos != x) {
chd[x][1] = pos, siz[x] = siz[pos] + 1;
} else {
siz[x] = 1;
}
} else {
ans += sum[x] - 1, siz[x] = 1;
}
}

inline void Modify(int x, LL y) {
sum[x] += y, tag[x] += y;
}

inline bool IsRoot(int x) {
return chd[f[x]][0] != x && chd[f[x]][1] != x;
}

inline void PushUp(int x) {
siz[x] = siz[chd[x][0]] + siz[chd[x][1]] + 1;
}

inline void PushDown(int x) {
if (tag[x]) {
Modify(chd[x][0], tag[x]), Modify(chd[x][1], tag[x]), tag[x] = 0;
}
}

inline void Rotate(int x) {
int y = f[x], z = f[y], k = chd[y][1] == x;
if (!IsRoot(y)) {
chd[z][chd[z][1] == y] = x;
}
f[chd[y][k] = chd[x][!k]] = y;
f[f[chd[x][!k] = y] = x] = z;
PushUp(y), PushUp(x);
}

inline void Splay(int x) {
static int top, sta[N];
sta[top = 1] = x;
for (int i = x; !IsRoot(i); sta[++top] = i = f[i]);
for (; top; PushDown(sta[top--]));
for (int y = f[x], z = f[y]; !IsRoot(x); Rotate(x), y = f[x], z = f[y]) {
if (!IsRoot(y)) {
Rotate((chd[y][1] == x) == (chd[z][1] == y) ? y : x);
}
}
}

inline int FindLeft(int x) {
if (!x) {
return 0;
}
for (; chd[x][0]; x = chd[x][0]);
Splay(x);
return x;
}

inline void Access(int x, int y) {
static int cur[N], lst[N], sta[N];
int top = 0;
cur[1] = x, a[x] += y;
for (int t; x; x = f[x]) {
Splay(x), t = FindLeft(chd[x][1]), Splay(x), chd[x][1] = 0;
PushUp(x), Modify(x, y), PushDown(x);
++top, lst[top] = t, sta[top] = x;
chd[x][1] = t, cur[top + 1] = FindLeft(x), Splay(x);
}
for (int i = 1; i <= top; ++i) {
int x = sta[i];
Splay(x);
if (lst[i]) {
ans -= sum[x] - y - sum[lst[i]] << 1;
} else if (a[x] - (i == 1 ? y : 0) << 1 > sum[x] - y) {
ans -= sum[x] - y - a[x] + (i == 1 ? y : 0) << 1;
} else {
ans -= sum[x] - y - 1;
}
if (lst[i]) {
if (sum[lst[i]] << 1 > sum[x]) {
ans += sum[x] - sum[lst[i]] << 1;
} else {
if (i != 1) {
Splay(cur[i]);
if (sum[cur[i]] << 1 > sum[x]) {
ans += sum[x] - sum[cur[i]] << 1;
chd[x][1] = cur[i], PushUp(x);
} else if (a[x] << 1 > sum[x]) {
ans += sum[x] - a[x] << 1;
chd[x][1] = 0, PushUp(x);
} else {
ans += sum[x] - 1;
chd[x][1] = 0, PushUp(x);
}
} else {
if (a[x] << 1 > sum[x]) {
ans += sum[x] - a[x] << 1;
chd[x][1] = 0, PushUp(x);
} else {
ans += sum[x] - 1;
chd[x][1] = 0, PushUp(x);
}
}
}
} else {
if (i != 1) {
Splay(cur[i]);
if (sum[cur[i]] << 1 > sum[x]) {
ans += sum[x] - sum[cur[i]] << 1;
chd[x][1] = cur[i], PushUp(x);
} else if (a[x] << 1 > sum[x]) {
ans += sum[x] - a[x] << 1;
} else {
ans += sum[x] - 1;
}
} else {
if (a[x] << 1 > sum[x]) {
ans += sum[x] - a[x] << 1;
} else {
ans += sum[x] - 1;
}
}
}
}
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
for (int i = 1; i <= n; ++i) {
}
for (int i = 1, x, y; i < n; ++i) {
}
DFS(1);
printf("%lld\n", ans);
for (int i = 1, x, y; i <= m; ++i) {
printf("%lld\n", ans);
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}

### maze

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

inline LL Solve(LL l, LL m, LL k) {
LL d = __gcd(m, k);
if (d == 1) {
return l;
} else {
if (l > k / d) {
if (k / (k - l) >= m) {
return m / d * (k - l) + Solve(k / d - m / d * (k - l), m, k / d);
} else {
return k / d;
}
} else {
return l;
}
}
}

int Main() {
LL m, k;
return 0;
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int T;
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120