
日记
不计代价。
不过我要是真的能做到 不计代价 的学习的话,我就不会那么菜了。
DFS Order 2Link to
我们想到,一个子树内的 dfs 序肯定是连续的,我们考虑跑一个背包。设 表示 在第 个被访问的方案数。我们先想总共有多少个 dfs 序。那么显然,如果有 个子树,那么就有 个子树排列的方式。每个子树又有自己的排列方式,乘起来就是了。 就是总的排列方式数。初始化就完了。
考虑如何转移:我们想从 。我们发现,一次加的肯定是一整个子树。那么我们想:做背包!设 表示 两个点在 dfs 序上相距 的方案数。转移有显然的 。
但是我们发现:子树之间是不分顺序的,我们转移 的时候还得扣掉 的子树。我们不可能对于每个子树都做个不考虑它的背包,那么复杂度直奔 ,显然不可取。
我们想:效仿淀粉质!每次扣掉 的子树所做的贡献,转移完再加回来。我们在每个 的子树转移时设单独的 。表示在 个子树内总共选了 个点的方案数。那么初始化有 。转移有显然的 。
那么我们又如何从 呢?对于 ,有 ,三项分别表示 个子树内的方案数, 个儿子排列的方案数,剩下儿子排列的方案数。
但是我们输出发现:比例正确,值错误。我们直接化到最简。我们发现比例正确但是值不正确的原因是有 ,所以就是直接化到最简。
Core code:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
\\ 预处理
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 ExpectationsLink to
原题也做不起吗?
我们考虑 ctj 设 表示在 个困难之后花费了 分钟的方案数。那么有转移:
具体来讲,就是如果还有可能破纪录,就尝试能不能破纪录。反之直接重开。但是我们发现这玩意有后效性,直接高斯消元。高斯消元肯定是不可取的,毕竟有个 在那里镇着。我们考虑二分 。如果最终的 比 小,就说明有些本该重开的我们选择了继续打,往小二分。反之往大二分。
糖果大战Link to
高斯消元 yyds
游走Link to
此游走非彼游走。
设总共有 条路径,总长为 。那么直接 dfs 搜出每个以每个点为起点的路径数量和路程总长,一加一除就出来了。
如果这题没模我不炸了?
汉堡 BurgerLink to
题意简化:有一个 01 串,0 的数量和 1 的数量各占一半。且最后的两个是连续的 1,求出这么滴的概率。
正难则反。设 为长度为 的不成立的概率。那么显然有 。我们发现这题没模,不能预处理阶乘。考虑推式子。推得 。答案就是 。
后日谈 Link to 后日谈
我都写 Java 了我还管常数吗?
好想念小学时无忧无虑的周末啊。。。
日记
© 伊埃斯 | CC BY-NC-SA 4.0