计数相关

狄利克雷卷积式
(displaystyle [n=1]=sum_{d|n} μ(d))

(n)个点的树(有标号)

(n^{n-2})

(n)个点的环套树(有标号)

(displaystyle frac {sum_{k=3}^{n} n^{n-k} prod_{l=1}^{k-1} (n-l) } {2})

杜教筛

构造函数(g(i))
(displaystyle g(1)s(n)=sum_{i=1}^n (f*g)(i) - sum_{i=2}^n g(i)s(n/i))
数论分块计算,记忆化,复杂度(O(n^{2/3}))

一种扩展杜教筛法

[sum_{i=1}^n (f*g)(i) = sum_{ijle n}f(i)g(j) ]

(N)个点的环套树(有标号)证明

先选出一个环,再决定环的顺序,再把整个环跟其他点串起来,需要用到 ( ext{prufer}) 序列有关的芝士 。

[F(n)=sum_{i=3}^N {Nchoose i} frac{(i-1)!}{2} * i * N^{N-i-1} \ =frac{(N-1)!}{2}sum_{i=0}^{N-3}frac{N^i}{i!} ]

(N)个点的环套树(有标号)计数

考虑EGF,设环套树的EGF为F(x),有根树的EGF为G(x)。
枚举环多大,然后把若干个有根树挂在环上:

[F(x)=sum_{k>2} frac{(k-1)!}{2} frac{G^k(x)}{k!} \ = frac{1}{2}sum_{k>2}frac{G^k(x)}{k} ]

求导以后求逆解决,积分回来即可:

[F'(x) = frac{1}{2} sum_{k>2} frac{k·G^{k-1}(x)·G'(x)}{k} = frac{1}{2} G'(x)G^2(x) frac{1}{1-G(x)} ]

多项式牛顿迭代形式

设有一方程 (G(F(x))=0 pmod {x^n})
假如对于这个 (n) 我们求得 $$G(f(x))=0 pmod {x^{left lceil frac{n}{2} ight ceil}}$$
那么有:$$F(x)=f(x)-dfrac{ G(f(x)) }{ G'(f(x)) } pmod {x^n}$$
边界是 (n=1),倍增复杂度是 (O(nlog n))
多项式求逆、多项式开根和多项式 (exp) 均使用此方法推导。

有标号DAG

只考虑不一定连通的;
根据上述即 (f(n)=sum_{i=1}^n (-1)^{i+1} {nchoose i}f(n-i)2^{i(n-i)}),推一下可以多项式求逆。

有标号二分图

设连通的二分图egf是(f(x)),然后定义黑白图表示黑白染色的二分图,那么连通的黑白图egf是(2f(x))
那么由组合意义普通黑白图的egf是 (F(x)=exp 2f(x))
(F(x)) 易于求出,设 (h_i) 表示 (i) 个点黑白图的个数,可以枚举有几个涂黑,(h_i=sum_{j+k=i} {ichoose j} 2^{jk})
通过单次多项式乘法可以得到 (F(x)),然后整个都能算了。复杂度 (O(nlog n))
如果只要求普通二分图,可以考虑多项式开根,复杂度 (O(nlog n))

常系数线性递推

首先如果对矩阵的特征多项式取模可得

[A^n=sum_{i=0}^{k-1} r_iA^i ]

现在求的是

[Ans=PA^n[0]=sum_{i=0}^{k-1} r_iPA^i[0] ]

发现初始向量乘 (i) 个转移矩阵相当于左移 (i) 位,那么有 (Ans=sum_{i=0}^{k-1} r_iP_i)

现在计算 (r_i) 特征多项式为 (B(x)=x^k-a_1x^{k-1}-cdots-a_{k-1}x-a_k)
倍增做多项式取模,常数是快速幂的 (1over 2)

伯努利数预处理幂和多项式

很多筛法题要求幂和然后 (kle 300) 然后可以 (O(k^2)) 预处理幂和多项式以后很方便做。

设B数的生成函数是:

[B(x)={xover e^x-1}=sum_{i=0}^infty B_ix^i ]

可以推出幂和多项式 $$A_k(x)=k! sum_{j=1}^{k+1} {B_{k+1-j}over j!}x^j$$

然后显然最高次项是 (x^{k+1}),代码如下

for(int i = 0; i <= n; i++) {
	for(int j = i + 1; j <= n; j++)
		B[j] = (B[j] - 1ll * B[i] * ifac[j - i + 1]) % mod;
	(B[i] += mod) %= mod;
}
++B[1];
v[0] = {0, 1};
for(int i = 1; i <= n; i++)
{
	v[i].resize(i + 2);
	for(int j = 1; j <= i + 1; j++)
		v[i][j] = 1ll * B[i + 1 - j] * fac[i] % mod * ifac[j] % mod;
	for(auto &x : v[i])
		printf("%d ", x);
	puts("");
}
原文地址:https://www.cnblogs.com/bestwyj/p/10354104.html