📅  最后修改于: 2023-12-03 15:11:13.621000             🧑  作者: Mango
生成函数是组合数学中的一种方法,可以用于解决组合计数问题。它将序列(通常是组合数序列)表示为一个形式幂级数的系数。
形式幂级数是指一个无穷个变量构成的级数,我们通常用 $F(x)$ 这样的形式表示,其中 $x$ 代表着变量。例如:
$$ F(x) = \sum_{n \geq 0} a_n x^n $$
在生成函数的应用中,$a_n$ 通常是某个图形问题的解,而 $x$ 则表示某种状态(如色彩、位置、大小等)。
有种生成函数称为普通生成函数,它的定义如下:
$$ F(x) = \sum_{n \geq 0} a_n x^n $$
其中 $a_n$ 代表着组合计数问题的答案。
另一种生成函数的形式如下:
$$ F(x) = \sum_{k \geq 0} \frac{a_k}{k!} x^k $$
我们称其为指数型生成函数。这种生成函数通常用于统计排列,因为排列问题与阶乘 $n!$ 相关。
一些组合问题与阶乘相关,因此我们还有另一种生成函数,称之为阶乘型生成函数。它的定义如下:
$$ F(x) = \sum_{n \geq 0} \frac{a_n}{n!} x^n $$
其中 $a_n$ 是问题的解。这种生成函数在组合计数中是最常见的。
生成函数可以应用于各种组合问题,例如:
生成函数的实现通常涉及到多项式运算,因此需要对多项式的加、减、乘、求导等基本操作有一定的掌握。C++ 中可以使用 STL 库的 valarray 类来实现。以下是一个示例代码:
#include <bits/stdc++.h>
using namespace std;
typedef valarray<double> Poly;
Poly operator+(const Poly &a, const Poly &b) {
Poly res(max(a.size(), b.size()));
for (size_t i = 0; i < res.size(); ++i) {
if (i < a.size()) res[i] += a[i];
if (i < b.size()) res[i] += b[i];
}
return res;
}
Poly operator-(const Poly &a, const Poly &b) {
Poly res(max(a.size(), b.size()));
for (size_t i = 0; i < res.size(); ++i) {
if (i < a.size()) res[i] += a[i];
if (i < b.size()) res[i] -= b[i];
}
return res;
}
Poly operator*(const Poly &a, const Poly &b) {
Poly res(a.size() + b.size() - 1);
for (size_t i = 0; i < a.size(); ++i)
for (size_t j = 0; j < b.size(); ++j)
res[i + j] += a[i] * b[j];
return res;
}
Poly operator&(const Poly &a, const Poly &b) {
Poly res(a.size() + b.size() - 1);
for (size_t i = 0; i < a.size(); ++i)
for (size_t j = 0; j < b.size(); ++j)
res[i + j] += a[i] * b[j];
return res;
}
void D(Poly &a) { // 求导数
size_t n = a.size();
for (size_t i = 1; i < n; ++i) a[i - 1] = a[i] * i;
if (n) a[n - 1] = 0;
}
void I(Poly &a) { // 积分
size_t n = a.size();
for (int i = n - 1; i >= 1; --i) a[i] = a[i - 1] / i;
if (n) a[0] = 0;
}
void get_ord(int &m) { // 获取m值
printf("请输入 m 值:\n");
scanf("%d", &m);
}
void input(Poly &a, Poly &b) { // 输入两个多项式
int n, m;
printf("请输入多项式 A 的次数:\n");
scanf("%d", &n);
a.resize(n + 1);
printf("请依次输入 A 的系数:\n");
for (int i = 0; i <= n; ++i) scanf("%lf", &a[i]);
printf("请输入多项式 B 的次数:\n");
scanf("%d", &m);
b.resize(m + 1);
printf("请依次输入 B 的系数:\n");
for (int i = 0; i <= m; ++i) scanf("%lf", &b[i]);
}
void solve(Poly &a, Poly &b) { // 求解
int m;
get_ord(m);
a.resize(m + 1);
D(a);
b.resize(m + 1);
I(b);
Poly ans = (a & b);
for (int i = 0; i <= m; ++i) printf("%.3lf ", ans[i]);
}
int main() {
Poly A, B;
input(A, B);
solve(A, B);
return 0;
}
生成函数的实现还可以涉及到 FFT、NTT 等高级算法,这里不再一一列出。