Atcoder abc303
https://atcoder.jp/contests/abc303/tasks
G - Bags Game
n包, i个x[i]钱
每次3选1
- 获得 最左/最右 一个
- 获得 最左/最右 (一共B个,可以分别取一部分) - A元
- 获得 最左/最右 (一共D个,可以分别取一部分) - C元
两人交替, 分别是X,Y, 求X-Y 的双方最优操作后的值,一个要最大,一个要最小
n 3000
xi,a,b,c,d, 1e9
2.5s
1024mb
我的思路
如果没有后两种
那就是经典的dp[l][r] =
从当前开始最优差值
dp[l][r] = max(x[l] - dp[l+1][r], x[r] - dp[l][r-1])
现在多了两种批量的情况
例如其中第二个方案就是 x[l...i] + x[j...r] - A - dp[i+1][j-1], len(l..i)+len(j..r) == B
但是注意到可以变换一下
x[l...r] - x[i+1..j-1] - A - dp[i+1][j-1], len(l..i)+len(j..r) == B
令 ndp[i..j] = x[i..j] + dp[i..j]
dp[l..r] = max(x[l] - dp[l+1][r],x[r]-dp[l][r-1],x[l..r] - A/C - ndp[i+1..j-1])
不妨设 第一种是 支付E=0元,取得F=1个
dp[l..r] = x[l..r] - min(A/C/E + ndp[i+1..j-1,A/C/E])
因此 需要一个 能够快速查询
[l...r]
区间内 A/C/E + min(ndp[len(l..r)-B/D/F])
即可
minndp[l..r]
可以通过minndp[l-1..r-1]
维护小根堆转移得到
代码
https://atcoder.jp/contests/abc303/submissions/42716988
1 |
|
Ex - Constrained Tree Degree
给定 范围在[1,N-1]的K个数字的集合S
问点标签1~N的N点树且所有点的度
$\in S$ 的树的个数 mod 998244353
n [2,2e5]
5s
1024mb
我的思路
首先 如果没有1, 那么肯定没有方案,所以考虑有1的情况, 所有叶子都是好的
那么如何唯一的表示一棵树???
考虑从根节点开始,每次放置的是 当前可延伸的最小节点
这样有性质, 不能小于它已经存在的兄弟节点
这样就可以用 [大小,最后值]
来表示, 每次放置以后 大小+1, 最后值变为新放入的, 并且多出一个[0,0]
而除了根,最终的大小+1
$\in S$
然而感觉这就是 暴力得不能再暴力了,复杂度爆炸
我发现问题是,即使没有限制,我好像也不知道如何统计n点树的个数
这样一想
那先去掉限制
上面的方法维护的内容过多了,特别是这个最后的值
换个方式
1 开始,每次选点都是对所有叶子节点的最左选择所有的分支
这样对于1来说,出度为d的话,就是binom(n-1,d)
f(可放置叶子数量,剩余点个数)
$f(l,n) = \sum_{t=0\cdots n} f(l-1 + t, n-t) \binom{n}{t}$, 这样在最左候选点放置t个
令$g(i=l+n,j=n) = f(l,n)$
$g(i,j) = f(i-j,j) = \sum_{t=0\cdots j} f(i-j-1+t,j-t) \binom{j}{t}$, 这里变形后需要额外处理 $i \le j,g(i,j) = 0$吗???????????????????????????????????????????
$= \sum_{t=0\cdots j} g((i-j-1+t) + (j-t),j-t) \binom{j}{t}$
$= \sum_{t=0\cdots j} g(i-1,j-t) \binom{j}{t}$
$=j! \sum_{t=0\cdots j} \frac {g(i-1,j-t)}{(j-t)!} \frac{1}{t!}$
令$h(i,j) = \frac{g(i,j)}{j!}$
$h(i,j) = \sum_{t=0\cdots j}h(i-1,j-t) \frac{1}{t!}$
生成方程 $H_i(x) = H_{i-1}(x) e^x$
这样的话
其实就是 binom
这一块会变,也就是不可以选的t要让$\binom{n}{t}$ 变为$0$
这就直接让对应的$\frac{1}{t!} = 0$即可
依然要注意的是,根和非根不一样,所以上面小改一下变成f(可放置叶子数量,剩余点的个数,是否为根)
令$E_0(x) = \sum_{i,i \in S} \frac{1}{i!}x^i$
$E_1(x) = \sum_{i,i+1 \in S} \frac{1}{i!}x^i$
$E_0(x) = E_1(x) x$
要求的是ans = f(1,n-1,true) = g(n,n-1,true) = h(n,n-1,true) * (n-1)!
然而问题是这样的话,上面的依次计算 是n^2 log n
的样子,虽然比暴力小了不少依然不行
所以 快速幂的方法
$H_n(x,true) = H_{n-1}(x,false)\star E_0(x) = H_0(x) E_1^{n-1}(x) E_1(x) x$
$ans = (n-1)! [x^{n-1}]H_{n}(x,true) = (n-1)! [x^{n-2}] E_1^{n}(x)$
样例1为例
n = 4, k = 2
s1=1,s2=3
ans = f(1,3,true) = g(1+3,3,true) = h(4,3,true) 3!
[x^3] H_4(x,true) = [x^3] H_3(x,false) (x+x^3/3!)
= [x^3] (1+x^2/2!)^3 (x+x^3/3!)
= 3/2! + 1/3!
$ans = 10$ 并不对
f(1,3,true) = f(3,0,false) + f(1,2,false) 3!
g(3+0,0,false) = 1
g(3+0,2,false) = 1
h(3,0,false) = 1/0! = 1
h(3,2,false) = 1/2! = 1/2!
但如果每次处理高位零才对
$h_1(x) = 1 + x^2/2! \mod x^1 = 1$
$h_2(x) = h_1(x) (1+x^2/2!) \mod x^2 = 1$
$h_3(x) = h_2(x) (1+x^2/2!) \mod x^3 = 1 + x^2/2!$
这样 $ans = 3! [x^3] (1+x^2/2!)(x+x^3/3!) = 3!(1/2!+1/3!) = 4$
所以如何 快速计算
$h_n(x) = h_{n-1}(x) E(x) \mod x^n$ 呢?
题解
Prüfer code
对于一个 无根 树,每次选择最小的叶节点,删除并向队列A(初始空)中添加这个被删节点连接的点,这样直到剩下两个节点
那么 队列A和树一一对应
性质
- 构造完后剩下的两个节点里,一定有一个是编号最大的节点。
- 对于一个 n度的节点,其必定在序列中出现 n−1 次. 因为每次删去其子节点它都会出现一次,最后一次则是删除其本身。推论: 一次都未出现的是原树的叶子节点。
还原:
根据性质2,显然把序列未出现的最小的叶子节点 和 A[0]
连接,那么变成了 A[1:]
的子问题, 重复操作即可
至此关于prufer code的 正向和逆向证完,注意到还原操作显然的唯一性,而任何树可以产生队列,因此一一对应
另一方面,对于任意长度N-2,值域[1,N]
的序列,抽屉原理长度 < 剩余点数
, 所以总可以建立新的边, 而且 注意到 每次是一个队列中和队列外的建立边,所以永不成环, 另一方面不成环的n点n-1条边 一定是连通成树的不会不连通,所以神奇的这样有N^{N-2}个树
而基于这个性质,问题变成有多少个 长度n-2值序列1~N,且每个值出现次数在 {s_i-1} 中呢
这样就无脑做了 $(N-2)![x^{N-2}] (\sum_{i+1\in S} \frac{1}{i!}x^i)^N$
代码
1 |
|
总结
G
没怎么想也想出来了,这题评分怎么这么高不科学,
Ex
感觉比G难但是 评分却更低,第一次见 Prüfer code,学习了
在大的思路还是在向生成方程靠拢,但是搞了一个我自己不会快速计算的 $H_n(x) = H_{n-1}(x) E(x) \mod x^n$
$\displaystyle F(x) = \sum_{i+1\in S} \frac{1}{i!}x^i$
$\displaystyle G_0(x) = 1$
$\displaystyle G_n(x) = G_{n-1}(x) F(x) \mod x^n$
$\displaystyle (n-1)[x^{n-2}]G_n(x) =?= [x^{n-2}]F^n(x)$
这对吗,以及如果对的话,这$F(x)$换成一般的也相等吗?