狄利克雷卷积

预备知识

生成函数

母函数

普通生成函数

形式:f(x)=∑(n≥0)anxn

加减: f(x)±g(x)=∑(an±bn)xn→f(x)±g(x) 是 <an±bn> 的普通生成函数

乘法运算:(卷积)

f(x)g(x)=∑n≥0xn∑i=0naibn−i,(i+j=n)

即 f(x)g(x) 是 ∑i=0naibn−i 的普通生成函数

可以用于解决多重集组合数问题,(指数是物品个数,系数是组合数)

应用

有 n 个物品,每种物品有 ai 个,求取 m 个物品的组合数 (不看顺序)?

设从每种物品选择 bi 个 (0≤bi≤ai),则 m=∑i=1nbi

构造普通生成函数 (1+x+x2+…xa1)(1+x+⋯+xa2)….(1+x+x2+⋯+xan)

即求 xm 的系数

即 ∑i=0naibn−i

例 1: HDU 2152

在本题只有 bi 范围变化: li≤bi≤ri,还是求 xm 的系数

#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 的硬币各 a1,a2,a3 枚,求不能组成的最小面值是多少。

构造生成函数 L (1+x+x2+…xa1)(1+x2+x4+⋯+x2a2)(1+x5+⋯+x5a3)

遍历到系数为 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;
            }
        }
    }
}
指数生成函数

形式: f(x)=∑n≥0anxnn!

则 <1,1,1,…,1> 的指数生成函数是 ex
<1,p,p2,⋯> 的指数生成函数是 epx

加减运算和普通生成函数性质相同

乘法运算:

f(x)g(x)=∑n≥0xnn!∑i=0nCniaibn−i

则 f(x)g(x) 是序列 <∑i=0nCniaibn−i> 的指数生成函数

应用

HDU 1521
有 n 个物品,每种物品有 ai 个,求取 m 个物品的排列数 (看顺序)?

设从每种物品选择 bi 个 (0≤bi≤ai),则 m=∑i=1nbi

对于一组选定的 bi 排列方案数是 m!b1!b2!…bn!

由于 HDU 这个题运算不会超过 231,所以可以用 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';
    }
}

狄利克雷卷积

狄利克雷生成函数形式:f(x)=∑i=1∞annx

乘法运算:

f(x)g(x)=∑n=1∞1nx∑d|nadbnd

Note

积性函数:f(1)=1,且当 gcd(a,b)=1→f(ab)=f(a)f(b)

欧拉函数和莫比乌斯函数都是积性函数

对于欧拉函数有性质:∑d|nφ(d)=n

对于莫比乌斯函数有性质:∑d|nμ(d)=[n=1]

对于二者之间的联系:∑d|nμ(d)nd=φ(n)

定义狄利克雷卷积:

f(n),g(n) 是积性函数, (f×g)(n)=∑d|nf(d)g(nd)=∑d|nf(nd)g(n)

符合交换律,结合律,分配律

三个常用函数:

有: f∗ϵ=f,f∗1≠f

常用卷积关系: