多项式&生成函数做题记录

开坑!最后有我的多项式板子。

\(\text{T1}\):AT_agc005_f

对于每一个 \(u\) 分别考虑。反面考虑,计算 \(u\) 不被放进点集的方案数。于是我们可以得到 \(u\) 的贡献为:

\[\dbinom nk-\dbinom{n-siz_u}{k}-\sum_{v \in son_u}\dbinom{siz_v}{k} \]

然后我们考虑直接求和,可得:

\[f(k)=n \times \dbinom nk - (\sum_{u \neq rt} \dbinom{siz_u}{k} + \dbinom{n-siz_u}{k}) \]

然后我们考虑用一个桶 \(cnt_i\) 表示有多少个 \(siz_u=i\)\(n-siz_u=i\)。然后我们继续化简式子,得:

\[\begin{array}{l} f(k)=n \times \dbinom nk - \sum_{i=k}^n cnt_i \times \dbinom ik \\=n \times \dbinom nk - \sum_{i=k}^n cnt_i \times \dfrac{i!}{(i-k)! \times k!} \\=n \times \dbinom nk - \dfrac{1}{k!}\sum_{i=k}^n cnt_i \times \dfrac{i!}{(i-k)!} \\=n \times \dbinom nk - \dfrac{1}{k!}\sum_{i=k}^{n-k} cnt_{k+i} \times \dfrac{1}{i!} \times (i+k)! \end{array} \]

此时我们令 \(g(x) = \dfrac{1}{x!},f(x) = (n-x)! \times cnt_{n-x}\)。所以:

\[f(k)=n \times \dbinom nk - \dfrac{1}{k!}\sum_{i=0}^{n-k} g(i)f(n-i-k) \]

这个式子就可以直接用 NTT 算啦!

\(\text{T2}\):P4173

FFT 匹配字符串。

考虑定义一个函数 \(dis(S,T) = \sum_{i=0}^{n-1} (A_i-B_i)^2 \times A_i \times B_i\)。容易发现,当 \(A_i == B_i\)\(A_i,B_i\) 中任意一个是通配符时,\(dis(S,T) = 0\)

那么 \(A\)\(B\) 能匹配的条件就是 \(f_i = dis(A,B[i-m+1,i]) = 0\)。考虑拆开 \(f_i\),得:

\[f_i=\sum^i_{j=0}A_j^3B_{i-j} - 2\sum^i_{j=0}A_j^2B_{i-j} + \sum^i_{j=0} A_jB_{i-j}^3 \]

然后 \(3\) 次 FFT 就行啦!

\(\text{T3}\):P4199

发现直接求出答案十分不好求,于是可以先求先求出位置关于某根轴对称的回文子序列数量然后再减掉回文串的数量即可。

回文串数量直接用 Manacher 即可,接下来考虑如何求出关于某根轴对称的回文子序列数量。

定义 \(f_i = \sum^i_{j=0} S_{j} = S_{2 \times i - j}\)。然后根据二项式定义可得第 \(i\) 个位置的答案即为 \(2^{f_i} - 1\)。那么问题就变为了 \(f_i\) 怎么求。

此时我们构造 \(g_i = [S_i == a]\)\(h_i = [S_i == b]\),那么我们就可以得到:

\[f = g * g + h * h \]

然后就做完啦!

\(\text{T4}\): CF891E

软软萌萌 EGF!

我们发现每一次答案的增量即为 \(\prod a_i\) 的减少量。那么我们此时设 \(b_i\) 表示第 \(i\) 个数最终减了多少个 \(1\)。那么我们最终的答案即为 \(\prod a_i - \prod(a_i - b_i)\)。那么我们只需要考虑如何计算 \(\prod(a_i - b_i)\) 的期望了。

现在我们考虑一组 \(\sum b_i\) 的期望。

\[\mathbb E = \frac{1}{n^k}\frac{k!}{\prod^n_{i=1}b_i!}\prod(a_i - b_i)=\frac{k!}{n^k}\prod^n_{i = 1}\frac{a_i - b_i}{b_i!} \]

考虑 \(\frac{a_i - b_i}{b_i!}\) 能否用 EGF 做。现在考虑构造指数型生成函数:

\[\hat f_i(x) = \sum^{\infty}_{j = 0} \frac{a_j - x}{j}x^j = \sum^{\infty}_{j = 0}\frac{a_i}{j!} x^j - \sum^{\infty}_{j = 0} \frac{x \times x^{j - 1}}{(j - 1)!} = (a_i - x)e^x \]

那么对于整体来说,我们有:

\[\hat F(x) = \prod^n_{i = 1} \hat f_i = e^{nx}\prod^n_{i=1}(a_i - x) \]

然后现在的任务就是求出 \([x^k]\hat F(x)\)。考虑令:

\[G(x) = \prod^n_{i = 1}(a_i - x)=\sum^n_{i=1}c_ix^i \]

然后我们就有:

\[[x^k] \hat F(x) = \sum^n_{i = 0} c_i\frac{n^{k-i}}{(k-i)!} \]

然后回溯一下就有:

\[\mathbb E=\sum^n_{i=0}c_i\frac{k!}{(k-i)!n^i} \]

然后你直接 \(\mathrm O(n^2)\) 把算 \(G(x)\) 算出来即可。

\(\text{T}\infty\):my poly

namespace Poly
{
	int qpow(int a,int b)
	{
		int res = 1;
		while(b)
		{
			if(b & 1)res = res * a % mod;
			a = a * a % mod;b >>= 1;
		}
		return res;
	}
	void Der(int *f,int *g,int len)
	{
		for(int i = 0;i < len;i++)g[i] = f[i + 1] * (i + 1) % mod;
		g[len - 1] = 0;
	}
	void Int(int *f,int *g,int len)
	{
		for(int i = 1;i < len;i++)g[i] = f[i - 1] * qpow(i,mod - 2) % mod;
		g[0] = 0;
	}
	void FFT(int *a,int x,int K)
	{
		static int rev[maxn],lst;
		int n = 1 << x;
		if(n != lst)
		{
			for(int i = 0;i < n;i++)rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << x - 1);
			lst = n;
		}
		for(int i = 0;i < n;i++)if(i < rev[i])swap(a[i],a[rev[i]]);
		for(int i = 1;i < n;i <<= 1)
		{
			int tmp = i << 1,wn = qpow(3,(mod - 1) / tmp);
			if(K == -1)wn = qpow(wn,mod-2);
			for(int j = 0;j < n;j += tmp)
			{
				int w = 1;
				for(int k = 0;k < i;k++,w = w * wn % mod)
				{
					int x = a[j + k],y = w * a[i + j + k] % mod;
					a[j + k] = (x + y) % mod;a[i + j + k] = (x - y + mod) % mod;
				}
			}
		}
		if(K == -1)
		{
			int inv = qpow(n,mod - 2);
			for(int i = 0;i < n;i++)a[i] = a[i] * inv % mod;
		}
	}
	void Inv(int *f,int *g,int len)
	{
		static int A[maxn];
		if(len == 1)return g[0] = qpow(f[0],mod - 2),void();
		Inv(f,g,len >> 1);copy(f,f + len,A);
		int x = log2(len << 1),n = 1 << x;
		fill(A + len,A + n,0);fill(g + (len >> 1),g + n,0);
		FFT(A,x,1);FFT(g,x,1);
		for(int i = 0;i < n;i++)g[i] = (mod + 2 - A[i] * g[i] % mod) * g[i] % mod;
		FFT(g,x,-1);fill(g + len,g + n,0);
	}
	const int inv2 = (mod + 1) / 2;
	void Sqrt(int *f,int *g,int len)
	{
		static int A[maxn],B[maxn];
		if(len == 1)return g[0] = sqrt(f[0]),void();
		Sqrt(f,g,len >> 1);Inv(g,B,len);
		copy(f,f + len,A);
		int x = log2(len << 1),n = 1 << x;
		fill(A + len,A + n,0);fill(B + len,B + n,0);
		fill(g + (len >> 1),g + n,0);
		FFT(A,x,1);FFT(B,x,1);FFT(g,x,1);
		for(int i = 0;i < n;i++)g[i] = (g[i] + A[i] * B[i] % mod) % mod * inv2 % mod;
		FFT(g,x,-1);fill(g + len,g + n,0);
	}
	void Ln(int *f,int *g,int len)
	{
		static int A[maxn],B[maxn];
		Der(f,A,len),Inv(f,B,len);
		int x = log2(len << 1),n = 1 << x;
		fill(A + len,A + n,0);fill(B + len,B + n,0);
		FFT(A,x,1);FFT(B,x,1);
		for(int i = 0;i < n;i++)A[i] = A[i] * B[i] % mod;
		FFT(A,x,-1);Int(A,g,len);
	}
	void Exp(int *f,int *g,int len)
	{
		static int A[maxn];
		if(len == 1)return g[0] = 1,void();
		int x = log2(len << 1),n = 1 << x;
		Exp(f,g,len >> 1);
		fill(A + len,A + n,0);fill(g + (len >> 1),g + n,0);
		Ln(g,A,len);
		A[0] = (f[0] + 1 - A[0] + mod) % mod;
		for(int i = 1;i < len;i++)A[i] = (f[i] - A[i] + mod) % mod;
		FFT(A,x,1);FFT(g,x,1);
		for(int i = 0;i < n;i++)g[i] = g[i] * A[i] % mod;
		FFT(g,x,-1);fill(g + len,g + n,0);
	}
	void Pow(int *f,int len,int k)
	{
		static int A[maxn];
		Ln(f,A,len);
		for(int i = 0;i < len;i++)A[i] = A[i] * k % mod;
		Exp(A,f,len);
	}
}using namespace Poly;
posted @ 2025-01-29 15:28  sqrtqwq  阅读(23)  评论(1)    收藏  举报