狄利克雷卷积
预备知识
生成函数
母函数
普通生成函数
形式:
加减:
乘法运算:(卷积)
即
可以用于解决多重集组合数问题,(指数是物品个数,系数是组合数)
应用
有
设从每种物品选择
构造普通生成函数
即求
即
例 1: HDU 2152
在本题只有
#define int long long
void 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 long
void 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;
}
}
}
}
指数生成函数
形式:
则
加减运算和普通生成函数性质相同
乘法运算:
则
应用
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';
}
}
狄利克雷卷积
狄利克雷生成函数形式:
乘法运算:
Note
积性函数:
,且当
欧拉函数和莫比乌斯函数都是积性函数
对于欧拉函数有性质:
对于莫比乌斯函数有性质:
对于二者之间的联系:
定义狄利克雷卷积:
符合交换律,结合律,分配律
三个常用函数:
- 元函数:
- 常数函数:
- 恒等函数:
有:
常用卷积关系: