求混合背包(某一体积的物品可能有无限个也可能有有限个),得到体积和为
1...n的方案数。
热身题。
如果一个体积为
v的物品有无限个,那么其关于体积的普通生成函数为
∑i=0xvi=1−xv1
如果一个体积为
v的物品有
K个,那么其关于体积的普通生成函数为
∑i=0Kxvi=1−xv1−xv(K+1)
将这些生成函数乘起来即可得到答案的生成函数。
发现总项数可能达到
n2不能直接上多项式乘法,可以考虑对每个式子取
ln求和后求
exp。
ln(1−x)泰勒展开可以得到为
∑i=1i−xi
所以对于
ln1−xv1=−ln1−xv=∑i=1ixiv
ln1−xv1−xv(K+1)=∑i=1ixiv−∑i=1ixiv(K+1)
求出
xiv中
v=v0的系数和后即可
O(nlnn)求和得到
ln后的式子求和的生成函数。
代码
社论
fk(x)=i=1∑x−1fk(i)+xk,fk(1)=1
这个式子是一个
n阶递推,既不是齐次也不是线性。
我们可以化一下式子变成常系数非齐次线性递推。
fk(x)=fk(x−1)+(i=1∑x−2fk(i)+(x−1)k)+xk−(x−1)k=2fk(x−1)+xk−(x−1)k
这是个一阶常系数非齐次线性递推。
我们知道如果是齐次的话,因为这个递推式只有一阶,第
n项可以用递推式的特征根的
n次方之类用快速幂解决。
变成齐次的方法很简单,
构造递推式
gk(x)=2gk(x−1)−xk+(x−1)k
所以
(fk(x)+gk(x))=2(fk(x−1)+gk(x−1))。
我们求的
fk(x)=2x−1(fk(1)+gk(1))−gk(n)
考虑到我们需要的
gk(x)只需要满足一个递推式,发现有且仅有一个
k−1次多项式
gk(x)满足这个方程。
也就是说
gk(x)可以是一个
k−1次多项式。
那么我们只需要求出
gk(0...k−1)即可拉格朗日插值得到
gk(n),从而算出
fk(n)。
分别求出
0...k的
k次方后,可以通过假设
gk(0)递推得到
gk(k),然后通过拉格朗日插值得到
gk(k)的另一个表达式,解出
gk(0)即可。
Code
社论
容易发现这个顺序其实类似于树的拓扑序反过来。
当两个初始点重合的时候就是求树的拓扑序计数。
经典结论:答案为
∏i in treeszin!,其中
szi是以初始黑点为根时
i的子树的大小。
当两个初始点不重合时,新建一个点
s,将初始点和
s连边。
那么我们将会得到一颗基环树,枚举环上的一条边割掉,我们就可以把问题看做以
s为初始黑点求树的拓扑序计数。
考虑割掉的这条边,它左右两边的点中一定恰好有一个是环上最后一个被染成红色的点,所以对于一种情况有两种可能的割边(最后一个被染成红色的点左右有两条边),所以最后答案要
÷2。
然后在两个初始黑点中选一个为根求出每个点的子树大小,其中两个初始黑点间的链的每个点的子树大小依次记为
c1,c2...cn,再在左边加一个
c0=0,注意这里
c1...cn是递增的。
那么
∣ci−cj∣在
i>j时的意义就是在
j→j+1这条链断开时的
i的子树大小。
在
i<j时的意义就是在
j→j+1这条链断开时的
i+1的子树大小。
所以在断开
j→j+1时的链上的
∏sz=∏i!=j∣ci−cj∣,不在链上的预处理即可。
那么我们只需要求
∑j∏i!=j∣ci−cj∣1,发现这个东西和多项式快速插值的第一部分一模一样。
具体的设
F(x)=∏j∣x−cj∣,有
∏i!=j∣ci−cj∣=x−ciF(x)∣∣∣x=ci
因为
F(ci)=(ci−ci)=0用洛必达法则,有:
∏i!=j∣ci−cj∣=F(ci)′
分治
FFT后求导套多点求值即可。
Code
社论
容斥做法:
枚举有具体
k列放了两颗石子,具体的
2n−2k列放了一颗石子的方案数为
Sk。
ans=k=0∑n(km)(2n−2km−k)Sk
求
Sk,考虑容斥掉同一行的两颗石子不能在同一列这个限制。
Sk=2n+k1i=0∑k(in)(ik)(−1)ii!2i(2n−2i)!
这里枚举的
i是同一行的两颗石子在同一列的次数。
统计时将同一行的两个石子看做不同,放在同一列的两个石子先后有顺序,这样统计
2n−2i个石子放入剩下还空着的列时可以直接写
(2n−2i)!,相对应的需要在外面
÷2n÷2k(有
k列可以放两个石子)。
i!表示这
i行都分别有两个重合的石子,将他们分配给
i列的方案,
2i是因为这两个石子之间有顺序。
Sk=2n+kn!k!i=0∑k(k−i)!1i!(n−i)!(−2)i(2n−2i)!
就可以卷积求出
Sk,然后直接求得答案了。
还有一种多项式
exp但是不写
exp的推法,本质应该有点类似,具体可以看上面的博客。
Code
社论
dp1:fi,j=fi−1,j+fi−1,j−1(ai+j),
fi,j表示前
i个数选了
j数的贡献和。
发现这个
dp我不太会做。
换一下定义:
fi,j表示前
i个数选了
i−j个数的贡献和。
dp2:fi,j=fi−1,j−1+fi−1,j(ai+i−j)=fi−1,j−1−jfi−1,j+fi−1,j(ai+i)
考虑组合意义(和第二类斯特林数相似):对于每个
i我们有三种选择,
不选,代价
×(ai+i),
选,加入前面
j个组中的一个,代价
×(−j),
选,新建一个组,代价无变化。
不选
i个的代价可以用分治
FFT求
∏i=1n(x+ai+i)
选
i个的代价,可以先考虑选一组的指数生成函数是
−(e−x−1),
(ex−1)是非空集合带标号的指数生成函数,我们这里除了第一个数,别的数加入还需要
×−1,所以是
−(e−x−1)。
那么选
i个的代价的生成函数就是
exp(1−e−x),注意是指数生成函数还需要除阶乘。
然后将选和不选的生成函数卷积一下求
xn项即可。
Code
福利题快速幂模板题
单位根反演:
k1∑i=0k−1wkij=[k∣j]
当
wkj=1时,即
[k∣j]时,原式
=kk=1
否则原式
=k(1−wkj)1−wkkj=0
所以对于此题:
∑i=0n[k∣i](in)=k1∑i=0n∑j=0k−1wkij(in)
=k1∑j=0k−1∑i=0nwkij(in)=k1∑j=0k−1(1+wkj)n
此题模数很友好,求出单位根后快速幂即可。
Code
设
fu,i,0/1表示
u子树内选了
i个点,其中
u选没选为第三维的答案,
那么树链剖分后建出全局平衡二叉树,对于虚儿子到父亲的转移即为
fu的分治
FFT。
对于重儿子到父亲,对重链分治,对于每一边求出
gi,0/1,0/1表示重链的某部分即下方的虚子树,头是否被选为第二维,尾是否被选为第三维。
对重链分治的时候可以按照下面子树的
sz分治而非对半分治,可以优化常数。
O(nlog3n)很好证明。
但是有人说这样写是
O(nlog2n)的
Code
F(x)=∑i=0i!2(2i)xi有标号无向图数量。
D(x)=ϑlnF(x)=[lnF(x)′]x即有根有标号联通无向图数量。
B(x)=∑i=1i!bi+1xi,
bi为
i个点的无根有标号点双连通图数量。
那么一个有根有标号联通无向图的根节点周围可以挂若干个包含根的点双,挂一个大小为
i+1的点双,那么除了根以外的
i个点,每个点删去和该点双其他点的连边后的连通块是一个有根有标号联通无向图。
D(x)=xexp[∑i=1i!bi+1D(x)i]=xexpB[D(x)]
假设
G[D(x)]=x即他们互为复合逆。
那么
D(G(x))=G(x)expB[D(G(x))]
也即:
x=G(x)expB(x)
B(x)=lnG(x)x
令
lnxD(x)=C(x)
则有
C(G(x))=lnG(x)x=B(x)
又根据扩展拉格朗日反演可以得到:
[xn]B(x)=[xn]C(G(x))=[xn−1]nD(x)nC(x)′xn=[xn−1]nC(x)′×(D(x)x)n=[xn−1]nC(x)′exp(−nlnxD(x))=[xn−1]nC(x)′exp(−nC(x))
首先可以看到
发现这个条件让你可以直接多次拉格朗日反演求出大小
∈S的所有点双连通图的方案数,设他的生成函数为
C(x)。
然后和点双联通图计数一样的方法设答案为
F(x)。
那么考虑包含根的点双,把这些点双的边删掉之后,所有的点都可以挂一个我们正在求的图也即
F(x),然后自由组合。
所以可以得到方程:
F(x)=xexpC(F(x))
发现有:
expC(F(x))F(x)=x
所以
F(x)和
expC(x)x互为复合逆。
[xn]F(x)=[xn−1]nexpC(x)nxnxn=[xn−1]nexpnC(x)
Code
题意:对于
k=1...n,求在树上选
k个点的所有方案中,在这
k个点中某两个点的最短路径上的点数。
发现对于选
k个点,答案是一个连通块,所以边数
=点数
−1,所以我们计算总边数最后加上
(kn)即可。
对于一条边
(a,b),它在这个连通块内即代表这
k个点不在同一边,假设一边的大小为
sz,则它在这个连通块内的方案数为
(kn)−(ksz)−(kn−sz)
将组合数拆开
k!×(ksz)=(sz−k)!sz!
做一下差卷积即可将
(ksz)贡献到每个
k。
Code
0~9种有k种可用数字,求前n/2个数字和与后n/2个数字和相等的方案数
对一个最高次数为
9的多项式求它的
105次幂即可。
可以直接做
1e6的
NTT然后把每个点值快速幂后再
NTT回来即可。
也可以通过
g=fk,g′=kfk−1f′得到
g′f=kgf′
ngnf0=∑i=19kifign−i−∑i=19(n−i)fign−i,
f0=0可以通过平移多项式解决。
从而
O(81n)得到
g=fk。