题目描述

定义两个函数 \(f, g: \{1, 2, \dots, n\} \rightarrow \mathbb Z\) 的狄利克雷卷积 \(f * g\) 为:

\[(f * g)(n) = \sum_{d | n} f(d)g(\frac nd)
\]

我们定义 \(g = f^k\) 即 \(k\) 次幂为:

\[f^{k}=\underbrace {f * \dots * f} _{k~{\textrm {个}}}
\]

在本题中,我们想要解决这个问题的逆问题:给你 \(g\) 和 \(k\),你需要找到一个函数 \(f\) 使得 \(g = f^k\)。

另外,保证 \(g(1)=1\),你需要保证 \(f(1)=1\)。所有的运算在 \(\mathbb F_p\) 上进行,其中 \(p = 998244353\),这意味着狄利克雷卷积为 \((f*g)(n) = \left(\sum_{d|n} f(d)g(\frac nd)\right) \bmod p\)。

\(n\le 10^6\)

Sol

定义一个数论函数 \(f(n)\) 的狄利克雷生成函数是 \(F(x)=\sum_{n=1}^\infty f(n)n^x\)。

注意这个东西不是关于 \(x\) 的多项式(一开始我当成了多项式),然而它可以做多项式乘法,由于这个 \(a^x\cdot b^x \rightarrow (ab)^x\),所以对于生成函数系数来说,相当于完成了两个数论函数的 狄利克雷卷积

既然有类似多项式的性质,那么我们考虑 ln-exp 的方法求解 k 次根。

根据多项式 ln 的推导,有 \(B=\ln A\rightarrow B=\int {A'\over A}\)

除法可以用 狄利克雷除法 实现,那么我们只需要支持 导数和积分 运算即可。

考虑这个指数函数的求导法则 \(\displaystyle {\text{d} a^x\over \text{d}x}=a^x\ln a\)。

然而在正整数意义下没有 \(\ln\) 这种运算,然后做法是找一个运算性质跟 \(\ln\) 一样的东西来替代它,比如质因子个数函数 \(\text{cnt}_x\)(相同的算作多个),因为它满足 \(f(x)+f(y)=f(xy)\) 这样的性质。

于是可以实现一个对一个狄利克雷级数求对数函数的代码如下:

  1. void ln(int n, int *a)
  2. {
  3. b[1] = 0;
  4. for(int i = 2; i <= n; ++i)
  5. b[i] = (ll)a[i] * cnt[i] % P;
  6. for(int i = 2; i <= n; ++i)
  7. {
  8. for(int j = 2, k = i * j; k <= n; ++j, k += i)
  9. b[k] = (b[k] - 1LL * b[i] * a[j]) % P;
  10. b[i] = (1LL * b[i] * inv[cnt[i]] % P + P) % P;
  11. }
  12. for(int i = 1; i <= n; ++i)
  13. a[i] = b[i];
  14. }

由于 \(B=A^{1/k}=\exp {{\ln A} \over k}\),那么只要先求 \(\ln\) 再 \(\exp\) 即可。

求指数函数也是类似的,整个代码如下,和暴力 \(O(n^2)\) 的普通多项式对数/指数函数非常相似。

  1. #include<stdio.h>
  2. typedef long long ll;
  3. const int N = 1000005, P = 998244353;
  4. int fexp(int a, int b)
  5. {
  6. ll x = 1, o = a;
  7. for(; b; b >>= 1, o = o * o % P)
  8. if(b & 1) x = x * o % P;
  9. return x;
  10. }
  11. int n, K, a[N], b[N], inv[128], cnt[N];
  12. bool np[N];
  13. void init()
  14. {
  15. cnt[1] = 1;
  16. for(int i = 2; i <= n; ++i)
  17. if(!np[i])
  18. {
  19. cnt[i] = 1;
  20. for(int j = 2, k = i * j; k <= n; j++, k += i)
  21. {
  22. np[k] = true;
  23. if(!cnt[k] && cnt[j]) cnt[k] = cnt[j] + 1;
  24. }
  25. }
  26. inv[1] = 1;
  27. for(int i = 2; i < 128; ++i)
  28. inv[i] = (ll)inv[P % i] * (P - P / i) % P;
  29. }
  30. void ln(int n, int *a)
  31. {
  32. b[1] = 0;
  33. for(int i = 2; i <= n; ++i)
  34. b[i] = (ll)a[i] * cnt[i] % P;
  35. for(int i = 2; i <= n; ++i)
  36. {
  37. for(int j = 2, k = i * j; k <= n; ++j, k += i)
  38. b[k] = (b[k] - 1LL * b[i] * a[j]) % P;
  39. b[i] = (1LL * b[i] * inv[cnt[i]] % P + P) % P;
  40. }
  41. for(int i = 1; i <= n; ++i)
  42. a[i] = b[i];
  43. }
  44. void exp(int n, int *a)
  45. {
  46. for(int i = 2; i <= n; ++i)
  47. b[i] = (ll)a[i] * cnt[i] % P, a[i] = 0;
  48. a[1] = 1;
  49. for(int i = 1; i <= n; ++i)
  50. {
  51. a[i] = 1ll * a[i] * inv[cnt[i]] % P;
  52. for(int j = 2, k = i * j; k <= n; ++j, k += i)
  53. a[k] = (a[k] + 1LL * a[i] * b[j]) % P;
  54. }
  55. }
  56. int main()
  57. {
  58. scanf("%d %d", &n, &K);
  59. for(int i = 1; i <= n; ++i)
  60. scanf("%d", a + i);
  61. init();
  62. K = fexp(K, P - 2);
  63. ln(n, a);
  64. for(int i = 1; i <= n; ++i) a[i] = 1ll * a[i] * K % P;
  65. exp(n, a);
  66. for(int i = 1; i <= n; ++i) printf("%d%c", a[i], " \n"[i == n]);
  67. return 0;
  68. }

LOJ#6713. 「EC Final 2019」狄利克雷 k 次根 加强版的更多相关文章

  1. [LOJ#2326]「清华集训 2017」简单数据结构

    [LOJ#2326]「清华集训 2017」简单数据结构 试题描述 参加完IOI2018之后就是姚班面试.而你,由于讨厌物理.并且想成为乔布斯一样的创业家,被成功踢回贵系. 转眼,时间的指针被指向201 ...

  2. Loj #2331. 「清华集训 2017」某位歌姬的故事

    Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...

  3. Loj #2324. 「清华集训 2017」小 Y 和二叉树

    Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...

  4. Loj #2321. 「清华集训 2017」无限之环

    Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ...

  5. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  6. 【刷题】LOJ 6227 「网络流 24 题」最长k可重线段集问题

    题目描述 给定平面 \(\text{xoy}\) 上 \(n\) 个开线段组成的集合 \(\text{I}\) ,和一个正整数 \(k\) ,试设计一个算法. 从开线段集合 \(\text{I}\) ...

  7. [LOJ#2330]「清华集训 2017」榕树之心

    [LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ...

  8. [LOJ#2329]「清华集训 2017」我的生命已如风中残烛

    [LOJ#2329]「清华集训 2017」我的生命已如风中残烛 试题描述 九条可怜是一个贪玩的女孩子. 这天她在一堵墙钉了 \(n\) 个钉子,第 \(i\) 个钉子的坐标是 \((x_i,y_i)\ ...

  9. [LOJ#2328]「清华集训 2017」避难所

    [LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所 ...

随机推荐

  1. C++——流类库与输入/输出

    I/O流的概念 当程序与外界环境进行信息交换时,存在着两个对象,一个是程序中的对象,另一个是文件对象,流是一种抽象,它负责在数据的生产者和数据的消费者之间建立连接,并管理数据的流动.程序建立一个流对象 ...

  2. Django学习笔记4

    Referto https://docs.djangoproject.com/zh-hans/2.2/intro/tutorial04/ Since we have the abstract conc ...

  3. axios的基本用法与并发请求

    一.axios的基本用法 <router-link to="" class="a1" @click.native="logins"&g ...

  4. Map merge

    将新的值赋值给map(如果不存在)或更新具有给定key的现有值. Map<Integer, Integer> map = new HashMap<>(); for (Integ ...

  5. JavaScript的流程控制

    JavaScript的流程控制 1.if...else if...else... 2.while 3.for 4.forEach 5.for...in... 完整代码如下: <!DOCTYPE ...

  6. TP5和TP3.2的使用区别

    模板标签不一样: TP5 可在配置文件中自行定义自己喜欢的标签 TP5  使用双标签 如:{foreach} {/foreach} TP3 : <> TP5 :{} 调用数据表方式: M( ...

  7. JVM&GC详解

    1.JVM简介 JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器.它是一种利用软件方法实现的抽象的计算机基于下层的操作系统和硬件平台,可以在上面执行java的字节码程序. ja ...

  8. DVWA全级别之File Upload(文件上传)

    File Upload File Upload,即文件上传漏洞,通常是由于对上传文件的类型.内容没有进行严格的过滤.检查,使得攻击者可以通过上传木马获取服务器的webshell权限,因此文件上传漏洞带 ...

  9. koa2第一天 async详解

    一.什么是async    async其实是ES7的才有的关键字,放在这里说,其实是和我们前面所说的Promise,Generator有很大关联的.async的意思是"异步",顾名 ...

  10. html表单提交给PHP然后浏览器显示出了PHP的源代码

    今天学习到PHP处理网页表单提交的数据时,碰到一个巨头疼的问题,先贴上案例代码: html表单部分: <html> <head> <meta charset=" ...