不计代价。
不过我要是真的能做到 不计代价 的学习的话,我就不会那么菜了。
DFS Order 2↗
我们想到,一个子树内的 dfs 序肯定是连续的,我们考虑跑一个背包。设 表示 在第 个被访问的方案数。我们先想总共有多少个 dfs 序。那么显然,如果有 个子树,那么就有 个子树排列的方式。每个子树又有自己的排列方式,乘起来就是了。 就是总的排列方式数。初始化就完了。
考虑如何转移:我们想从 。我们发现,一次加的肯定是一整个子树。那么我们想:做背包!设 表示 两个点在 dfs 序上相距 的方案数。转移有显然的 。
但是我们发现:子树之间是不分顺序的,我们转移 的时候还得扣掉 的子树。我们不可能对于每个子树都做个不考虑它的背包,那么复杂度直奔 ,显然不可取。
我们想:效仿淀粉质!每次扣掉 的子树所做的贡献,转移完再加回来。我们在每个 的子树转移时设单独的 。表示在 个子树内总共选了 个点的方案数。那么初始化有 。转移有显然的 。
那么我们又如何从 呢?对于 ,有 ,三项分别表示 个子树内的方案数, 个儿子排列的方案数,剩下儿子排列的方案数。
但是我们输出发现:比例正确,值错误。我们直接化到最简。我们发现比例正确但是值不正确的原因是有 ,所以就是直接化到最简。
Core code:
\\ 预处理int dfs1(int u,int fa){ int res = 1; siz[u] = 1,tot[u] = 0; for (auto &v : g[u]) { if (v == fa) continue; res = res * dfs1(v,u) % mod; siz[u] += siz[v],tot[u]++; } return res * fac[tot[u]] % mod;}
\\ 转移void dfs2(int u,int fa){ memset(f,0,sizeof f); f[0][0] = 1; for (auto &v : g[u]) { if (v == fa) continue; for (int i = tot[u]; i >= 1; i--) for (int j = siz[u]; j >= siz[v]; j--) f[i][j] = (f[i][j] + f[i - 1][j - siz[v]]) % mod; } for (auto &v : g[u]) { if (v == fa) continue; for (int i = 1; i <= tot[u]; i++) for (int j = siz[v]; j <= siz[u]; j++) f[i][j] = (f[i][j] - f[i - 1][j - siz[v]] + mod) % mod; memset(tmp,0,sizeof tmp); for (int i = 0; i < tot[u]; i++) for (int j = 0; j <= siz[u]; j++) tmp[j + 1] = (tmp[j + 1] + fac[i] * fac[tot[u] - 1 - i] % mod * f[i][j] % mod) % mod; for (int i = 1; i <= n; i++) for (int j = 1; i + j <= n; j++) dp[v][i + j] = (dp[v][i + j] + dp[u][i] * tmp[j]) % mod; for (int i = tot[u]; i >= 1; i--) for (int j = siz[u]; j >= siz[v]; j--) f[i][j] = (f[i][j] + f[i - 1][j - siz[v]]) % mod; } for (auto v : g[u]) if (v != fa) dfs2(v,u);}
\\ 输出化简for (int i = 1; i <= n; i++){ int sum = 0; for (int j = 1; j <= n; j++) sum = (sum + dp[i][j]) % mod; int tmp = binpow(sum,mod - 2); for (int j = 1; j <= n; j++) printf("%lld%c",dp[i][j] * dp[1][1] % mod * tmp % mod," \n"[j == n]);}Great Expectations↗
原题也做不起吗?
我们考虑 ctj 设 表示在 个困难之后花费了 分钟的方案数。那么有转移:
具体来讲,就是如果还有可能破纪录,就尝试能不能破纪录。反之直接重开。但是我们发现这玩意有后效性,直接高斯消元。高斯消元肯定是不可取的,毕竟有个 在那里镇着。我们考虑二分 。如果最终的 比 小,就说明有些本该重开的我们选择了继续打,往小二分。反之往大二分。
糖果大战↗
高斯消元 yyds
游走↗
此游走非彼游走。
设总共有 条路径,总长为 。那么直接 dfs 搜出每个以每个点为起点的路径数量和路程总长,一加一除就出来了。
如果这题没模我不炸了?
汉堡 Burger↗
题意简化:有一个 01 串,0 的数量和 1 的数量各占一半。且最后的两个是连续的 1,求出这么滴的概率。
正难则反。设 为长度为 的不成立的概率。那么显然有 。我们发现这题没模,不能预处理阶乘。考虑推式子。推得 。答案就是 。
后日谈
我都写 Java 了我还管常数吗?
好想念小学时无忧无虑的周末啊。。。
