生成函数

内容

形式幂级数

记作 \(A(x) = \sum_{i\ge0} a_i x^i\)

  1. 加法,\(A(x) + B(x) = \sum_{i \ge0} (a_i + b_i) x^i\)
  2. 减法,\(A(x) + B(x) = \sum_{i \ge0} (a_i - b_i) x^i\)
  3. 乘法,\(A(x)B(x) = \sum_{k \ge 0} \left (\sum_{i=0}^{k} a_{i}b_{k-i} \right ) x^k = \sum_{k \ge 0} \left ( \sum_{i+j=k} a_i b_j\right ) x^k\)

所以可知形式幂级数在如上运算定义下构成环。

形式幂级数 \(A(x)\) 的逆元:\(A(x)B(x) = 1\),存在条件为 \([x^0]A(x) \ne 0\)

常用的逆元:

  1. \(A(x) = 1 + x + x^2 + \cdots\)\(B(x) = 1 - x\),即 \(\frac{1}{1 - x} = \sum_{i\ge0}x^i\)
证明

\(s = 1 + x + x^2+ \cdots\),那么 \(s\cdot x = x + x^2 + x^3 + \cdots\),所以 \(s - s \cdot x = (1-x)s = 1\)\(s = \frac{1}{1-x}\)

  1. \(A(x) = 1 + ax + a^2x^2 + \cdots\)\(B(x) = 1 - ax\),即 \(\frac{1}{1 - ax} = \sum_{i\ge0}a^ix^i\)
证明

换元,只是将 \(x\) 换成了 \(ax\)

  1. \(A(x) = \binom{k-1}{0} + \binom{k}{1}x + \binom{k + 1}{2}x^2 + \cdots\)\(B(x) = (1-x)^k\),即 $\frac{1}{(1-x)^k} = \sum_{i\ge0} \binom{i+k-1}{i} x^i $。
证明

用归纳法易证。

假设对于 \(k\) 成立,那么 \(\frac{1}{(1-x)^k} = \sum_{i\ge0} \binom{i+k-1}{i} x^i\)

所以 \(\frac{1}{(1-x)^{(k+1)}} = \left (\sum_{i\ge0} \binom{i+k-1}{i} x^i \right)\left ( \sum_{i\ge0}x^i\right )\)

所以第 \(x^n\) 项的系数 \(c_n\)\(\sum\limits_{i=0}^{n} \binom{i + k - 1}{i} = \sum\limits_{i=0}^{n} \binom{i + k - 1}{k-1} = \binom{n+k}{k} = \binom{n+k}{n}\)。(曲棍球恒等式)

所以 \(\frac{1}{(1-x)^{(k+1)}} = \sum_{i\ge0} \binom{i+k}{i} x^i = \sum_{i\ge0} \binom{i+(k+1)-1}{i} x^i\)

显然对于 \(k=1\) 成立,证毕。

常生成函数

一个数列 \(\{ a_n \}\) 对应的常生成函数为 \(A(x) = \sum_{n\ge0} a_n x^n\)

有定理:设 \(S = \{ a_1, a_2, \cdots, a_k\}\),且 \(a_i\) 可以取的次数集合为 \(M_i\),记 \(F_i(x) = \sum_{u\in M_i} x^u\),则从 \(S\) 中取 \(n\) 个元素组成集合的方案数 \(g(n)\) 的常生成函数 \(G(x) = \sum_{i\ge0} g(i) x^i\) 满足 \(G(x) = F_1(x)F_2(x)\cdots F_k(x)\)

指数生成函数

咕咕咕。

例题(持续更新)

P6078 [CEOI 2004] Sweets

前缀和转换成求吃 \(1 \sim n\) 个糖果的总方案数是平凡的,考虑表示出每种糖果的生成函数:\(F_i(x) = \sum\limits_{k=0}^{m_i} x^k = \frac{1-x^{m\ _i\ +\ 1}}{1-x}\)

那么总方案数的生成函数就等于 \(G(x) = \prod F(x) = \frac{\prod 1-x^{m\ _i + 1}}{(1-x)^n} = \left (\prod 1-x^{m_i + 1} \right )\left ( \sum_{i \ge 0} \binom{n + i - 1}{i} x^i \right )\),现在即求 \(1 \sim num\) 的系数和。

左边是多项式乘法,由于只有 \(n = 20\) 项,可以直接暴力 \(\text{dfs}\)

假设左边乘出来其中一个 \(ax^b\),那么它能贡献的系数和就为 \(a \left ( \sum_{i+b \le num} \binom{n + i - 1}{i} \right )\)

现在考虑快速计算后面一坨和式,显然又可以用曲棍球杆恒等式:

\[\begin{array}{c} \sum_{i+b \le num} \binom{n + i - 1}{i}\\ = \sum\limits_{i = 0}^{num-b} \binom{n + i - 1}{n - 1} \\ = \binom{n+num-b}{n} \end{array} \]

然后你可以用 ex-Lucas 定理算,或者仿照洛谷第一篇题解。

CF451E Devu and Flowers

和上面那个一个题,可以参考一下代码:

点击查看代码
#include <bits/stdc++.h>
using namespace std;

#define x first
#define y second
#define db double
#define ll long long
#define pb push_back
#define vec vector
#define eb emplace_back
#define all(x) (x).begin(), (x).end()
#define MAXN 35
#define mod 1000000007

int n; ll s, inv = 1, ans = 0;
ll f[MAXN];
 
ll ksm(ll a, int b) {
	a %= mod;
	ll res = 1; 
	for (; b; a = a * a % mod, b >>= 1)
		if (b & 1) res = res * a % mod;
	return res;	
}

ll C(ll b) {
	ll res = 1;
	for (ll i = s - b + 1; i <= n + s - b - 1; ++i) 
		(res *= i % mod) %= mod;
	return (res * inv) % mod;
}

void dfs(int i, int v, ll b) {
	if (b > s) return ;
	if (i > n) {
		if (v > 0) 
			ans = (ans + C(b)) % mod;
		else 
			ans = (ans - C(b) + mod) % mod;
		return ;
	}	
	dfs(i + 1, v, b);
	dfs(i + 1, -v, b + f[i] + 1);
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> s;
	for (int i = 1; i <= n; ++i) 
		cin >> f[i]; 
	for (ll i = 1; i < n; ++i) inv *= i; 
	inv = ksm(inv, mod - 2);
	dfs(1, 1, 0);
	cout << ans % mod << '\n';
	return 0;
}
posted @ 2026-02-03 00:19  Statax  阅读(19)  评论(1)    收藏  举报