狄利克雷卷积

预备知识

生成函数

母函数

普通生成函数

形式:f(x)=(n0)anxn

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

乘法运算:(卷积)

f(x)g(x)=n0xni=0naibni(i+j=n)

f(x)g(x)i=0naibni 的普通生成函数

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

应用

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

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

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

即求 xm 的系数

i=0naibni

例 1: HDU 2152

在本题只有 bi 范围变化: libiri,还是求 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)=n0anxnn!

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

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

乘法运算:

f(x)g(x)=n0xnn!i=0nCniaibni

f(x)g(x) 是序列 <i=0nCniaibni> 的指数生成函数

应用

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

设从每种物品选择 bi 个 (0biai),则 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=1annx

乘法运算:

f(x)g(x)=n=11nxd|nadbnd

Note

积性函数:f(1)=1,且当 gcd(a,b)=1f(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,f1f

常用卷积关系: