Skip to content

Dirichlet卷积

母函数

形式:f(x)=(n0)anxn\displaystyle f(x)=\sum_{(n\geq 0)}a_{n}x^n

加减: f(x)±g(x)=(an±bn)xnf(x)±g(x)f(x)\pm g(x)=\sum(a_{n}\pm b_{n})x^n\to f(x)\pm g(x)<an±bn><a_{n}\pm b_{n}> 的普通生成函数

乘法运算:(卷积)

f(x)g(x)=n0xni=0naibni\displaystyle f(x)g(x)=\sum_{n\geq 0}x^n\sum_{i=0}^na_{i}b_{n-i}(i+j=n)(i+j=n)

f(x)g(x)f(x)g(x)i=0naibni\sum\limits_{i=0}^na_{i}b_{n-i} 的普通生成函数

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

nn 个物品,每种物品有 aia_{i} 个,求取 mm 个物品的组合数 (不看顺序)?

设从每种物品选择 bib_{i} 个 (0biai0\leq b_{i}\leq a_{i}),则 m=i=1nbim=\sum\limits_{i=1}^nb_{i}

构造普通生成函数 (1+x+x2+xa1)(1+x++xa2).(1+x+x2++xan)(1+x+x^2+\dots x^{a_{1}})(1+x+\dots+x^{a_{2}})\dots.(1+x+x^2+\dots+x^{a_{n}})

即求 xmx^{m} 的系数

i=0naibni\sum\limits_{i=0}^na_{i}b_{n-i}

例 1: HDU 2152

在本题只有 bib_{i} 范围变化: libiril_{i}\leq b_{i}\leq r_{i},还是求 xmx^m 的系数

Terminal window
#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,a3a_{1},a_{2},a_3 枚,求不能组成的最小面值是多少。

构造生成函数 L (1+x+x2+xa1)(1+x2+x4++x2a2)(1+x5++x5a3)(1+x+x^2+\dots x^{a_{1}})(1+x^2+x^4+\dots+x^{2a_{2}})(1+x^5+\dots+x^{5a_{3}})

遍历到系数为 0 的一项即可。

Terminal window
#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!\displaystyle f(x)=\sum_{n\geq 0}a_{n} \frac{x^n}{n!}

<1,1,1,,1><1,1,1,\dots,1> 的指数生成函数是 exe^x <1,p,p2,><1,p,p^2,\dots> 的指数生成函数是 epxe^{px}

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

乘法运算:

f(x)g(x)=n0xnn!i=0nCniaibni\displaystyle f(x)g(x)=\sum_{n\geq 0} \frac{x^n}{n!}\sum_{i=0}^nC_{n}^ia_{i}b_{n-i}

f(x)g(x)f(x)g(x) 是序列 <i=0nCniaibni><\sum \limits_{i=0}^nC_{n}^ia_{i}b_{n-i}> 的指数生成函数

HDU 1521nn 个物品,每种物品有 aia_{i} 个,求取 mm 个物品的排列数 (看顺序)?

设从每种物品选择 bib_{i} 个 (0biai0\leq b_{i}\leq a_{i}),则 m=i=1nbim=\sum\limits_{i=1}^nb_{i}

对于一组选定的 bib_{i} 排列方案数是 m!b1!b2!bn!\displaystyle \frac{m!}{b_{1}!b_{2}!\dots b_{n!}}

由于 HDU 这个题运算不会超过 2312^{31},所以可以用 double,平时的题目一般会取模的。

Terminal window
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\displaystyle f(x)=\sum_{i=1}^{\infty} \frac{a_{n}}{n^x}

乘法运算:

f(x)g(x)=n=11nxdnadbnd\displaystyle f(x)g(x)=\sum_{n=1}^{\infty} \frac{1}{n^x}\sum_{d|n}a_{d}b_{\frac{n}{d}}

[!NOTE]

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

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

对于欧拉函数有性质:dnφ(d)=n\displaystyle \sum_{d|n}\varphi(d)=n

对于莫比乌斯函数有性质:dnμ(d)=[n=1]\displaystyle \sum_{d|n}\mu(d)=[n=1]

对于二者之间的联系:dnμ(d)nd=φ(n)\displaystyle \sum_{d|n}\mu(d) \frac{n}{d}=\varphi(n)

定义狄利克雷卷积:

f(n),g(n)f(n),g(n) 是积性函数, (f×g)(n)=dnf(d)g(nd)=dnf(nd)g(n)\displaystyle (f\times g)(n)=\sum_{d|n}f(d)g\left( \frac{n}{d} \right)=\sum_{d|n}f\left( \frac{n}{d} \right)g(n)

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

三个常用函数:

  • 元函数:ϵ(n)=[n=1]\epsilon(n)=[n=1]
  • 常数函数:1(n)=11(n)=1
  • 恒等函数:id(n)=nid(n)=n

有: fϵ=f,f1ff*\epsilon=f,f*1\neq f

常用卷积关系:

  • dnμ(d)=[n=1]μ1=ϵ\displaystyle \sum_{d|n}\mu(d)=[n=1]\leftrightarrow \mu*1=\epsilon
  • dnφ(d)=nφ1=id\displaystyle \sum_{d|n}\varphi(d)=n\leftrightarrow \varphi*1=id
  • dnμ(d)nd=φ(n)μid=φ\displaystyle \sum_{d|n}\mu(d) \frac{n}{d}=\varphi(n)\leftrightarrow \mu*id=\varphi