生成函数
内容
形式幂级数
记作 \(A(x) = \sum_{i\ge0} a_i x^i\)。
- 加法,\(A(x) + B(x) = \sum_{i \ge0} (a_i + b_i) x^i\)。
- 减法,\(A(x) + B(x) = \sum_{i \ge0} (a_i - b_i) x^i\)。
- 乘法,\(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\)。
常用的逆元:
- \(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}\)。
- \(A(x) = 1 + ax + a^2x^2 + \cdots\) 和 \(B(x) = 1 - ax\),即 \(\frac{1}{1 - ax} = \sum_{i\ge0}a^ix^i\)。
证明
换元,只是将 \(x\) 换成了 \(ax\)。
- \(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 )\)。
现在考虑快速计算后面一坨和式,显然又可以用曲棍球杆恒等式:
然后你可以用 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;
}

浙公网安备 33010602011771号