FFT


NTT

将\(FFT\)中的单位复数根改成原根即可。

卡常版NTT模版

  1. struct Mul
  2. { int Len;
  3. int wn[N], Lim;
  4. int rev[N];
  5. inline void getReverse(int * a)
  6. {
  7. static int rev[N];
  8. rev[0] = 0;
  9. for (register int i = 0; i < Len; i++)
  10. {
  11. rev[i] = (rev[i>>1] >> 1) | ((i&1) ? (Len >> 1) : 0);
  12. if (i < rev[i]) swap(a[i], a[rev[i]]);
  13. }
  14. }
  15. void NTT(int * a, int opt)
  16. {
  17. getReverse(a);
  18. for (register int i = 0; i < Len; i += 2)
  19. {
  20. int x = a[i], y = 1LL * wn[0] * a[i + 1] % mod;
  21. a[i] = Plus(x, y), a[i + 1] = Minus(x, y);
  22. }
  23. for (register int i = 0; i < Len; i += 4)
  24. {
  25. int x1 = a[i], y1 = 1LL * wn[0] * a[i + 2] % mod;
  26. int x2 = a[i + 1], y2 = 1LL * wn[Lim / 2] * a[i + 3] % mod;
  27. a[i] = Plus(x1, y1), a[i + 2] = Minus(x1, y1);
  28. a[i + 1] = Plus(x2, y2), a[i + 3] = Minus(x2, y2);
  29. }
  30. for (register int i = 8; i <= Len; i <<= 1)
  31. {
  32. int M = i >> 1;
  33. for (register int j = 0; j < Len; j += i)
  34. {
  35. for (register int k = 0; k < M; k += 4)
  36. {
  37. int x1 = a[j + k], y1 = 1LL * wn[Lim / M * k] * a[j + k + M] % mod;
  38. int x2 = a[j + k + 1], y2 = 1LL * wn[Lim / M * (k+1)] * a[j + k + M + 1] % mod;
  39. int x3 = a[j + k + 2], y3 = 1LL * wn[Lim / M * (k+2)] * a[j + k + M + 2] % mod;
  40. int x4 = a[j + k + 3], y4 = 1LL * wn[Lim / M * (k+3)] * a[j + k + M + 3] % mod;
  41. a[j + k] = Plus(x1, y1), a[j + k + M] = Minus(x1, y1);
  42. a[j + k + 1] = Plus(x2, y2), a[j + k + M + 1] = Minus(x2, y2);
  43. a[j + k + 2] = Plus(x3, y3), a[j + k + M + 2] = Minus(x3, y3);
  44. a[j + k + 3] = Plus(x4, y4), a[j + k + M + 3] = Minus(x4, y4);
  45. }
  46. }
  47. }
  48. if (opt == -1)
  49. {
  50. for (register int i = 0; i < Len; i++)
  51. a[i] = 1LL * a[i] * inv[Len] % mod;
  52. for(register int i = 1; i < Len; i++)
  53. if(i < Len-i) swap(a[i], a[Len-i]);
  54. }
  55. }
  56. inline void init()
  57. {
  58. Lim = Len;
  59. wn[0] = 1; wn[1] = power(7, (mod-1) / (Len << 1), mod);
  60. for (int i = 2; i < (Len << 1); i++) wn[i] = 1LL * wn[i-1] * wn[1] % mod;
  61. }
  62. inline int getLen(int l)
  63. {
  64. for (Len = 1; Len <= l; Len <<= 1);
  65. return Len;
  66. }
  67. };

多项式求逆

也就是求

\[A(x)B(x) = 1 \pmod{x^n}
\]

假设我们已知

\[A(x)G(x) = 1 \pmod{x^{\lceil{n \over 2}\rceil}}
\]

两式相减得

\[A(x)(B(x) - G(x)) = 0 \pmod{x^{\lceil{n \over 2}\rceil}}
\]

\[B(x) - G(x) = 0 \pmod{x^{\lceil{n \over 2}\rceil}}
\]

\[B^2(x) + G^2(x) - 2B(x)G(x) = 0 \pmod{x^n}
\]

两边同时乘上\(A(x)\)

\[A(x)B^2(x) + A(x)G^2(x) = 2A(x)B(x)G(x)
\]

因为\(A(x)B(x) = 1\), 所以可以得到

\[B(x) + A(x)G^2(x) = 2G(x)
\]

\[B(x) = 2G(x) - A(x)G^2(x)
\]

就这样解决了

时间复杂度为\(T(n) = T(\frac{n}{2}) +O(n \log n)\)

代码

  1. inline void getInv(int * A, int * B, int len)
  2. {
  3. static int tmp1[N], tmp2[N];
  4. B[0] = power(A[0], mod-2, mod);
  5. for (register int k = 2; k <= len; k <<= 1)
  6. {
  7. int Len = k << 1;
  8. cpy(tmp1, A, k, Len);
  9. cpy(tmp2, B, (k >> 1), Len);
  10. Calc.Len = Len;
  11. Calc.NTT(tmp1, 1);
  12. Calc.NTT(tmp2, 1);
  13. for (int i = 0; i < Len; i++)
  14. tmp1[i] = Minus(Plus(tmp2[i], tmp2[i]), 1LL * tmp1[i] * tmp2[i] % mod * tmp2[i] % mod);
  15. Calc.NTT(tmp1, -1);
  16. cpy(B, tmp1, k, Len);
  17. }
  18. return;
  19. }

多项式开根

也就是求

\[B^2(x) = A(x) \pmod{x^n}
\]

假设我们已知

\[G^2(x) = A(x) \pmod{x^{\lceil{n \over 2}\rceil}}
\]

两式相减得

\[B^2(x) - G^2(x) = 0 \pmod{x^{\lceil{n \over 2}\rceil}}
\]

然后平方一下

\[B^4(x) + G^4(x) - 2B^2(x)G^2(x) = 0 \pmod{x^n}
\]

\[B^4(x) + G^4(x) = 2B^2(x)G^2(x) \pmod{x^n}
\]

配一下方

\[B^4(x) + G^4(x) + 2B^2(x)G^2(x) = 4B^2(x)G^2(x) \pmod{x^n}
\]

\[(B^2(x) + G^2(x))^2 = (2B(x)G(x))^2 \pmod{x^n}
\]

\[B^2(x) + G^2(x) = 2B(x)G(x) \pmod{x^n}
\]

因为\(A(x)B(x) = 1\), 所以可以得到

\[B(x) = {A(x) + G^2(x) \over {2G(x)}}
\]

为了方便实现,我们常把它化成

\[B(x) = {A(x) \over 2G(x)} + {G(x) \over 2}
\]

然后就解决了

时间复杂度为\(T(n) = T(\frac{n}{2}) + O(n \log n) = O(n \log n)\)


多项式求导

模拟即可

代码

  1. inline void getDeri(int * a, int len)
  2. { for (register int i = 0; i < len; i++)
  3. a[i] = 1LL * a[i+1] * (i+1) % mod;
  4. }

多项式积分

模拟即可

代码

  1. inline void getInte(int * a, int len)
  2. { for (int i = len-1; i >= 1; i--)
  3. a[i] = 1LL * a[i-1] * inv[i] % mod;
  4. a[0] = 0;
  5. }

多项式求\(\ln\)

已知多项式\(A(x)\), 求\(B(x) = \ln (A(x))\)

根据链式法则, 我们可以得到

\[B'(x) = \frac{\mathbb{d}(\ln(A(x)))}{\mathbb{d}A(x)} \frac{\mathbb{d}A(x)}{\mathbb{d}x} = \frac{A'(x)}{A(x)}
\]

所以

\[B(x) = \int \frac{A'(x)}{A(x)} \mathbb{d}x
\]

代码

  1. void getLn(int * A, int len)
  2. {
  3. static int tmp1[N], tmp2[N], tmp3[N];
  4. int Len = len << 1;
  5. cpy(tmp1, A, len, Len);
  6. cpy(tmp2, A, len, Len);
  7. getDeri(tmp1, len);
  8. getInv(tmp2, tmp3, len);
  9. Calc.Len = Len;
  10. Calc.NTT(tmp1, 1);
  11. Calc.NTT(tmp3, 1);
  12. for (int i = 0; i < Len; i++)
  13. tmp1[i] = 1LL * tmp1[i] * tmp3[i] % mod;
  14. Calc.NTT(tmp1, -1);
  15. memset(tmp1 + len, 0, 4 * (Len - len));
  16. getInte(tmp1, len);
  17. cpy(A, tmp1, len, Len);
  18. }

时间复杂度还是\(T(n) = T(\frac{n}{2}) + O(n \log n) = O(n \log n)\)


牛顿迭代

我们要求\(f(x) = 0\)的根

那么可以使用泰勒公式来近似\(f(x) = 0\)的根

我们设当前的近似值是\(x_{n}\), 我们想要得到的近似值是\(x_{n+1}\)

截取泰勒公式的线性部分: $$f(x_{n}) + f'(x_{n})(x_{n+1}-x_n) = 0$$

解方程得: $$x_{n+1} = x_n - \frac{f(x_{n})}{f'(x_{n})}$$

我们可以用这种方法来解多项式方程。


多项式\(\exp\)

我们要求的是 \(exp(A(x))\), 这相当于解一个方程: \(g(exp(A(x))) = \ln(exp(A(x))) - A(x) = 0\)

可以直接套用牛顿迭代法求解。

【Learning】多项式的一些东西的更多相关文章

  1. FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ

    众所周知,tzc 在 2019 年(12 月 31 日)就第一次开始接触多项式相关算法,可到 2021 年(1 月 1 日)才开始写这篇 blog. 感觉自己开了个大坑( 多项式 多项式乘法 好吧这个 ...

  2. FFT是个啥?

    简单来说就是一个计算多项式乘法的东西呀.. 以下内容基本都是在大黑书<算法导论>上的.. 总述 对于项数为$n$的多项式$A(x)$和项数为$m$的多项式$B(x)$,可以如此表达: $$ ...

  3. 【BZOJ3625】【CF438E】小朋友和二叉树

    题目 传送门 思路&做法 我们可以用\(v_i\)表示\(i\)在\(c\)中出现了几次, 用\(f_i\)表示权值为\(i\)的神犇树的总数, 于是 \[ f_x = \sum_{i = 0 ...

  4. 【learning】多项式乘法&fft

    [吐槽] 以前一直觉得这个东西十分高端完全不会qwq 但是向lyy.yxq.yww.dtz等dalao们学习之后发现这个东西的代码实现其实极其简洁 于是趁着还没有忘记赶紧来写一篇博 (说起来这篇东西的 ...

  5. 【learning】多项式相关(求逆、开根、除法、取模)

    (首先要%miskcoo,这位dalao写的博客(这里)实在是太强啦qwq大部分多项式相关的知识都是从这位dalao博客里面学的,下面这篇东西是自己对其博客学习后的一些总结和想法,大部分是按照其博客里 ...

  6. 【Learning】 多项式的相关计算

    约定的记号 对于一个多项式\(A(x)\),若其最高次系数不为零的项是\(x^k\),则该多项式的次数为\(k\). 记为\(deg(A)=k\). 对于\(x\in(k,+ \infty)\),称\ ...

  7. 【Learning】多项式乘法与快速傅里叶变换(FFT)

    简介: FFT主要运用于快速卷积,其中一个例子就是如何将两个多项式相乘,或者高精度乘高精度的操作. 显然暴搞是$O(n^2)$的复杂度,然而FFT可以将其将为$O(n lg n)$. 这看起来十分玄学 ...

  8. 【learning】多项式开根详解+模板

    概述 多项式开跟是一个非常重要的知识点,许多多项式题目都要用到这一算法. 用快速数论变换,多项式求逆元和倍增法可以在$O(n log n)$的时间复杂度下求出一个$n$次多项式的开根. 前置技能 快速 ...

  9. Machine Learning Algorithms Study Notes(4)—无监督学习(unsupervised learning)

    1    Unsupervised Learning 1.1    k-means clustering algorithm 1.1.1    算法思想 1.1.2    k-means的不足之处 1 ...

随机推荐

  1. xtu summer individual 6 F - Water Tree

    Water Tree Time Limit: 4000ms Memory Limit: 262144KB This problem will be judged on CodeForces. Orig ...

  2. 【转】Selenium专题—JQuery选择器

    juqery选择器是jquery库中非常重要的功能.jquery选择器是基于CSS1-3选择器,加上一些额外的选择器.这些选择器和CSS选择器的使用方法很相似,允许开发人员简单快速的识别页面上的元素. ...

  3. Memory Ordering in Modern Microprocessors

    Linux has supported a large number of SMP systems based on a variety of CPUs since the 2.0 kernel. L ...

  4. 使用JavaMail通过QQ/126服务器服务发送邮件

    https://blog.csdn.net/yidragon88xx/article/details/53230310

  5. 易碎的鸟蛋 概率DP

    1007: 易碎的鸟蛋 时间限制: 1 Sec  内存限制: 128 MB提交: 396  解决: 80[提交][状态][讨论版] 题目描述 你们知道吗?西电的跳楼塔上面有一个鸟巢.某SXBK的教授对 ...

  6. [bzoj3436]小K的农场_差分约束

    小K的农场 bzoj-3436 题目大意:给定n个点,每个节点有一个未知权值.现在有m个限制条件,形如:点i比点j至少大c,点i比点j至多大c或点i和点j相等.问是否可以通过给所有点赋值满足所有限制条 ...

  7. Java的文件注释

    以下内容引用自http://wiki.jikexueyuan.com/project/java/documentation.html: Java语言支持三种注释形式: 注释 描述 /*text*/ 编 ...

  8. 2011 ACM-ICPC 成都赛区A题 Alice and Bob (博弈动规)

    题目大意: 有K堆石子,每堆有Ki个.两人的操作能够是:             1 从某一堆拿走一个 假设该堆在此之后没有石子了.就消失             2 合并两个堆        求是否 ...

  9. 利用vue-cli配合vue-router搭建一个完整的spa流程

    好文章备忘录: 转自:https://segmentfault.com/a/1190000009160934?_ea=1849098 demo源码:https://github.com/1590123 ...

  10. Nginx中配置vue,react项目地址

    如题 像以前在Nginx中配置域名解析的时候只需要在conf.d文件夹下添加对应的xx.conf文件(当然了你也可以在nginx.conf)下配置. 如果是以前的老项目只需要在配置文件中server内 ...