[关闭]
@computerkiller 2021-03-25T08:04:17.000000Z 字数 2920 阅读 608

Dirichlet生成函数

数学


对于一些奇怪的数论问题有奇效。也是对数论函数的另一种视角。

基础形式

数列 的狄利克雷生成函数是

容易验证它的乘积就是狄利克雷卷积

狄利克雷函数初看非常的诡异,它和普通型与指数型不同,并不是一个形式幂级数。我们介绍一些典型的狄利克雷生成函数来了解它的性质。

典型函数

过于显然地 ,也就是数论中的 函数,的狄利克雷生成函数是 1。

zeta 函数

众所周知研究某型生成函数都要从 开始,也就是数论中的 函数,它的狄利克雷生成函数是

你可能已经在各种科普文上见过这个函数。这就是著名的黎曼 函数。

以及 不同,它的性质比较复杂,我们甚至不完全了解它的零点……不过这和接下来的介绍关系不大。

是一个(完全)积性函数,把 分解质因数后每个 对它的贡献是独立的,也就是说有下面的形式

这个形式会极大地方便我们讨论积性函数的性质。比如


那么它的逆就是

莫比乌斯函数

时贡献为 ,当 时贡献为 ,否则贡献为 ,正是莫比乌斯函数 。也就是说

ID 函数

显然就是

同理,

约数个数和

显然有

欧拉函数

从中可以立刻看出欧拉函数的筛法:

也就是说, 的贡献是

当质因数增加了一个 的时候按这个柿子更新贡献即可。

实际应用

例一

筛出

解答

它就是 ,容易知道 的贡献是

运算

我们继续来研究一下 DGF 的各种运算

下面我们讨论的 默认:

乘法

考虑:


直接卷 可以做到

高妙的高维前缀和可以做到 这里放板子题

求逆

事实上我们是要构造一个 满足:


按照多项式求逆的套路写:

一样倍增处理就好了qaq

复杂度是

积分和求导

先考虑求导好了 积分就是逆过程

求导的式子是:


我们重新定义 定义:

我们记我们定义的这个函数是

那么显然有

愉快地可以进行求导了 积分就是这个的逆过程 不多说了

取对数

直接快进到:


复杂度显然的

exp

性质还好:


提取系数:

和求逆一样倍增就好了

这堆板子看着就很好写 来一个:

  1. void derivation(int *f,int len,int *g)
  2. {
  3. for (int i = 1; i <= len; i++) g[i] = f[i] * c[i] % mod;
  4. }
  5. void integration(int *f,int len,int *g)
  6. {
  7. g[1] = f[1];
  8. for (int i = 2; i <= len; i++) g[i] = f[i] * inv[c[i]] % mod;
  9. }
  10. void mul(int *f,int *g,int len,int *h)
  11. {
  12. for (int i = 1; i <= len; i++)
  13. for (int j = 1; i * j <= len; j++)
  14. h[i * j] = (h[i * j] + f[i] * g[j]) % mod;
  15. }
  16. void getinv(int *f,int len,int *g)
  17. {
  18. g[1] = 1;
  19. for (int i = 1; i <= len; i++)
  20. for (int j = 2; i * j <= len; j++)
  21. g[i * j] = (g[i * j] - g[i] * f[j] % mod + mod) % mod;
  22. }
  23. void getln(int *f,int len,int *g)
  24. {
  25. derivation(f,len,A);
  26. getinv(f,len,B);
  27. mul(A,B,len,C);
  28. integration(C,len,g);
  29. for (int i = 1; i <= len; i++)
  30. A[i] = B[i] = C[i] = 0;
  31. }
  32. void getexp(int *f,int len,int *g)
  33. {
  34. derivation(f,len,A);
  35. g[1] = 1;
  36. for (int i = 1; i <= len; i++)
  37. {
  38. if (i > 1) g[i] = g[i] * inv[c[i]] % mod;
  39. for (int j = 2; i * j <= len; j++)
  40. g[i * j] = (g[i * j] + g[i] * A[j]) % mod;
  41. }
  42. for (int i = 1; i <= len; i++)
  43. A[i] = 0;
  44. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注