Dirichlet卷积
母函数
普通生成函数
Section titled “普通生成函数”形式:
加减: 是 的普通生成函数
乘法运算:(卷积)
,
即 是 的普通生成函数
可以用于解决多重集组合数问题,(指数是物品个数,系数是组合数)
有 个物品,每种物品有 个,求取 个物品的组合数 (不看顺序)?
设从每种物品选择 个 (),则
构造普通生成函数
即求 的系数
即
例 1: HDU 2152
在本题只有 范围变化: ,还是求 的系数
#define int long longvoid solve() { int n, m; while (cin >> n >> m) { vector<int> l(n + 1), r(n + 1), ans(201), tmp(201); for (int i = 1;i <= n;i++) { cin >> l[i] >> r[i]; } for (int i = l[1];i <= r[1];i++)ans[i] = 1; for (int i = 2;i <= n;i++) { for (int j = 0;j <= m;j++) { for (int k = l[i];k <= r[i];k++) { tmp[j + k] += ans[j]; } } ans = tmp;tmp.assign(201, 0); } cout << ans[m] << '\n'; }}例 2 HDU 1085 现有 1,2,5 的硬币各 枚,求不能组成的最小面值是多少。
构造生成函数 L
遍历到系数为 0 的一项即可。
#define int long longvoid solve() { int a[4] = {}; while (cin >> a[1] >> a[2] >> a[3] && (a[1] || a[2] || a[3])) { int b[4] = {0,1,2,5}; int m = a[1] * 1 + a[2] * 2 + a[3] * 5; vector<int> ans(m + 10), tmp(m + 10); for (int i = 0;i <= a[1];i++)ans[i] = 1; for (int i = 2;i <= 3;i++) { for (int j = 0;j <= m;j++) { for (int k = 0;k <= a[i] * b[i] && j + k <= m;k += b[i]) { tmp[j + k] += ans[j]; } } ans = tmp;tmp.assign(m + 10, 0); } for (int i = 0;i < ans.size();i++) { if (!ans[i]) { cout << i << "\n";break; } } }}指数生成函数
Section titled “指数生成函数”形式:
则 的指数生成函数是 的指数生成函数是
加减运算和普通生成函数性质相同
乘法运算:
则 是序列 的指数生成函数
HDU 1521 有 个物品,每种物品有 个,求取 个物品的排列数 (看顺序)?
设从每种物品选择 个 (),则
对于一组选定的 排列方案数是
由于 HDU 这个题运算不会超过 ,所以可以用 double,平时的题目一般会取模的。
void solve() { int n, m; while (cin >> n >> m) { vector<int> a(n + 1), ans(21), tmp(21); for (int i = 1;i <= n;i++) { cin >> a[i]; } for (int i = l[1];i <= r[1];i++)ans[i] = 1 / i!; for (int i = 2;i <= n;i++) { for (int j = 0;j <= m;j++) { for (int k = 0;k <= a[i];k++) { tmp[j + k] += ans[j] / k!; } } ans = tmp;tmp.assign(21, 0); } cout << ans[m] * m! << '\n'; }}狄利克雷卷积
Section titled “狄利克雷卷积”狄利克雷生成函数形式:
乘法运算:
[!NOTE]
积性函数:,且当
欧拉函数和莫比乌斯函数都是积性函数
对于欧拉函数有性质:
对于莫比乌斯函数有性质:
对于二者之间的联系:
定义狄利克雷卷积:
是积性函数,
符合交换律,结合律,分配律
三个常用函数:
- 元函数:
- 常数函数:
- 恒等函数:
有:
常用卷积关系: