疯狂补板中。

考虑倍增实现。

假设多项式只有一个常数项,直接对它逆元就可以了。

现在假如要求$G(x)$

$$F(x)G(x) \equiv 1 (\mod x^n)$$

而我们已经求出了$H(x)$

$$F(x)H(x) \equiv 1(\mod x^{\left \lceil \frac{n}{2} \right \rceil})$$

两式相减,

$$F(x)(G(x) - H(x)) \equiv 0(\mod x^{\left \lceil \frac{n}{2} \right \rceil})$$

$F(x) \mod  x^{\left \lceil \frac{n}{2} \right \rceil}$一定不会是$0$,那么

$$G(x) - H(x) \equiv 0(\mod x^{\left \lceil \frac{n}{2} \right \rceil})$$

两边平方,

$$G(x)^2 + H(x)^2 - 2G(x)H(x) \equiv 0(\mod x^n)$$

注意到后面的模数也平方了。

因为多项式$G(x) - H(x)$次数$\in [0, \left \lceil \frac{n}{2} \right \rceil]$的项的系数全都是$0$,所以平方之后次数在$[0, n]$之间的项的系数也全都是$0$。

两边乘上$F(x)$,

$$F(x)G(x)^2 + F(x)H(x)^2 - 2F(x)G(x)H(x) \equiv G(x) + F(x)H(x)^2 - 2H(x) \equiv 0(\mod x^n)$$

就得到了

$$G(x) \equiv 2H(x) - F(x)H(x)^2(\mod x^n)$$

递归实现比较清爽,非递归的比递归的快挺多的。

时间复杂度为$O(nlogn)$。

实现的时候有两个小细节:

1、$H(x)$的长度是$\frac{n}{2}$的,$F(x)$的长度是$n$,所以$F(x)H(x)^2$的长度是$2n$。

2、递归的时候注意那个上取整符号。

Code:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef long long ll;
  6.  
  7. const int N = << ;
  8.  
  9. int n;
  10. ll f[N], g[N];
  11.  
  12. namespace Poly {
  13. const int L = << ;
  14. const ll gn = ;
  15. const ll Mod[] = {, 998244353LL, 1004535809LL, 469762049LL};
  16.  
  17. int lim, pos[L];
  18.  
  19. inline ll fmul(ll x, ll y, ll P) {
  20. ll res = ;
  21. for (x %= P; y; y >>= ) {
  22. if (y & ) res = (res + x) % P;
  23. x = (x + x) % P;
  24. }
  25. return res;
  26. }
  27.  
  28. inline ll fpow(ll x, ll y, ll P) {
  29. ll res = 1LL;
  30. for (x %= P; y > ; y >>= ) {
  31. if (y & ) res = res * x % P;
  32. x = x * x % P;
  33. }
  34. return res;
  35. }
  36.  
  37. inline void prework(int len) {
  38. int l = ;
  39. for (lim = ; lim < len; lim <<= , ++l);
  40. for (int i = ; i < lim; i++)
  41. pos[i] = (pos[i >> ] >> ) | ((i & ) << (l - ));
  42. }
  43.  
  44. inline void ntt(ll *c, ll opt, ll P) {
  45. for (int i = ; i < lim; i++)
  46. if (i < pos[i]) swap(c[i], c[pos[i]]);
  47. for (int i = ; i < lim; i <<= ) {
  48. ll wn = fpow(gn, (P - ) / (i << ), P);
  49. if (opt == -) wn = fpow(wn, P - , P);
  50. for (int len = i << , j = ; j < lim; j += len) {
  51. ll w = ;
  52. for (int k = ; k < i; k++, w = w * wn % P) {
  53. ll x = c[j + k], y = c[j + k + i] * w % P;
  54. c[j + k] = (x + y) % P, c[j + k + i] = (x - y + P) % P;
  55. }
  56. }
  57. }
  58.  
  59. if (opt == -) {
  60. ll inv = fpow(lim, P - , P);
  61. for (int i = ; i < lim; i++) c[i] = c[i] * inv % P;
  62. }
  63. }
  64.  
  65. /* inline ll get(int k, ll P) {
  66. ll M = Mod[1] * Mod[2];
  67. ll t1 = fmul(Mod[2] * ans[1][k] % M, fpow(Mod[1], Mod[2] - 2, Mod[2]), M);
  68. ll t2 = fmul(Mod[1] * ans[2][k] % M, fpow(Mod[2], Mod[1] - 2, Mod[1]), M);
  69. ll t = (t1 + t2) % M;
  70. ll res = (ans[3][k] - t % Mod[3] + Mod[3]) % Mod[3];
  71. res = res * fpow(M, Mod[3] - 2, Mod[3]) % Mod[3];
  72. res = ((res % P) * (M % P) % P + (t % P)) % P;
  73. return res;
  74. } */
  75.  
  76. ll f[L], g[L];
  77. void inv(ll *a, ll *b, int len, ll P) {
  78. if (len == ) {
  79. b[] = fpow(a[], P - , P);
  80. return;
  81. }
  82. inv(a, b, (len + ) >> , P);
  83.  
  84. prework(len << );
  85. for (int i = ; i < lim; i++) f[i] = g[i] = ;
  86. for (int i = ; i < len; i++) f[i] = a[i], g[i] = b[i];
  87. ntt(f, , P), ntt(g, , P);
  88. for (int i = ; i < lim; i++) g[i] = g[i] * (2LL - f[i] * g[i] % P + P) % P;
  89. ntt(g, -, P);
  90. for (int i = ; i < len; i++) b[i] = g[i];
  91. }
  92.  
  93. };
  94.  
  95. template <typename T>
  96. inline void read(T &X) {
  97. X = ; char ch = ; T op = ;
  98. for (; ch > ''|| ch < ''; ch = getchar())
  99. if (ch == '-') op = -;
  100. for (; ch >= '' && ch <= ''; ch = getchar())
  101. X = (X << ) + (X << ) + ch - ;
  102. X *= op;
  103. }
  104.  
  105. int main() {
  106. read(n);
  107. for (int i = ; i < n; i++) read(f[i]);
  108. Poly :: inv(f, g, n, Poly :: Mod[]);
  109. for (int i = ; i < n; i++)
  110. printf("%lld%c", g[i], i == (n - ) ? '\n' : ' ');
  111. return ;
  112. }

递归版

  1. #include <cstdio>
  2. #include <cstring>
  3. using namespace std;
  4. typedef long long ll;
  5.  
  6. const int N = 3e5 + ;
  7. const ll P = 998244353LL;
  8.  
  9. int n, lim, pos[N];
  10. ll a[N], f[][N], tmp[N];
  11.  
  12. template <typename T>
  13. inline void read(T &X) {
  14. X = ; char ch = ; T op = ;
  15. for (; ch > '' || ch < ''; ch = getchar())
  16. if (ch == '-') op = -;
  17. for (; ch >= '' && ch <= ''; ch = getchar())
  18. X = (X << ) + (X << ) + ch - ;
  19. X *= op;
  20. }
  21.  
  22. template <typename T>
  23. inline void swap(T &x, T &y) {
  24. T t = x; x = y; y = t;
  25. }
  26.  
  27. inline ll fpow(ll x, ll y) {
  28. ll res = 1LL;
  29. for (; y > ; y >>= ) {
  30. if (y & ) res = res * x % P;
  31. x = x * x % P;
  32. }
  33. return res;
  34. }
  35.  
  36. inline void ntt(ll *c, int opt) {
  37. for (int i = ; i < lim; i++)
  38. if(i < pos[i]) swap(c[i], c[pos[i]]);
  39. for (int i = ; i < lim; i <<= ) {
  40. ll wn = fpow(, (P - ) / (i << ));
  41. if(opt == -) wn = fpow(wn, P - );
  42. for (int len = i << , j = ; j < lim; j += len) {
  43. ll w = ;
  44. for (int k = ; k < i; k++, w = w * wn % P) {
  45. ll x = c[j + k], y = c[j + k + i] * w % P;
  46. c[j + k] = (x + y) % P, c[j + k + i] = (x - y + P) % P;
  47. }
  48. }
  49. }
  50.  
  51. if (opt == -) {
  52. ll inv = fpow(lim, P - );
  53. for (int i = ; i < lim; i++) c[i] = c[i] * inv % P;
  54. }
  55. }
  56.  
  57. int main() {
  58. read(n);
  59. for (int i = ; i < n; i++) read(a[i]);
  60.  
  61. f[][] = fpow(a[], P - );
  62. int dep = ;
  63. for (int len = ; len < n; len <<= , ++dep) {
  64. lim = len << ;
  65. for (int i = ; i < lim; i++) tmp[i] = a[i];
  66.  
  67. lim <<= ;
  68. for (int i = ; i < lim; i++) pos[i] = (pos[i >> ] >> ) | ((i & ) << dep);
  69. for (int i = (len << ); i < lim; i++) tmp[i] = ;
  70.  
  71. int now = dep & , pre = (dep - ) & ;
  72. ntt(f[pre], ), ntt(tmp, );
  73. for (int i = ; i < lim; i++)
  74. f[now][i] = (2LL * f[pre][i] % P - tmp[i] * f[pre][i] % P * f[pre][i] % P + P) % P;
  75. ntt(f[now], -);
  76.  
  77. for (int i = (len << ); i < lim; i++) f[now][i] = ;
  78. }
  79.  
  80. --dep;
  81. for (int i = ; i < n; i++)
  82. printf("%lld%c", f[dep & ][i], i == (n - ) ? '\n' : ' ');
  83.  
  84. return ;
  85. }

非递归版

Luogu 4238 【模板】多项式求逆的更多相关文章

  1. 洛谷.4238.[模板]多项式求逆(NTT)

    题目链接 设多项式\(f(x)\)在模\(x^n\)下的逆元为\(g(x)\) \[f(x)g(x)\equiv 1\ (mod\ x^n)\] \[f(x)g(x)-1\equiv 0\ (mod\ ...

  2. 【洛谷4238】 多项式求逆(NTT,分治)

    前言 多项式求逆还是爽的一批 Solution 考虑分治求解这个问题. 直接每一次NTT一下就好了. 代码实现 #include<stdio.h> #include<stdlib.h ...

  3. 洛谷 P4238 [模板] 多项式求逆

    题目:https://www.luogu.org/problemnew/show/P4238 看博客:https://www.cnblogs.com/xiefengze1/p/9107752.html ...

  4. luogu P4725 多项式对数函数 (模板题、FFT、多项式求逆、求导和积分)

    手动博客搬家: 本文发表于20181125 13:25:03, 原地址https://blog.csdn.net/suncongbo/article/details/84487306 题目链接: ht ...

  5. [模板][P4238]多项式求逆

    NTT多项式求逆模板,详见代码 #include <map> #include <set> #include <stack> #include <cmath& ...

  6. 2018.12.30 洛谷P4238 【模板】多项式求逆

    传送门 多项式求逆模板题. 简单讲讲? 多项式求逆 定义: 对于一个多项式A(x)A(x)A(x),如果存在一个多项式B(x)B(x)B(x),满足B(x)B(x)B(x)的次数小于等于A(x)A(x ...

  7. 洛谷 P4721 [模板]分治FFT —— 分治FFT / 多项式求逆

    题目:https://www.luogu.org/problemnew/show/P4721 分治做法,考虑左边对右边的贡献即可: 注意最大用到的 a 的项也不过是 a[r-l] ,所以 NTT 可以 ...

  8. 洛谷P4238【模板】多项式求逆

    洛谷P4238 多项式求逆:http://blog.miskcoo.com/2015/05/polynomial-inverse 注意:直接在点值表达下做$B(x) \equiv 2B'(x) - A ...

  9. P4238 【模板】多项式求逆

    思路 多项式求逆就是对于一个多项式\(A(x)\),求一个多项式\(B(x)\),使得\(A(x)B(x) \equiv 1 \ (mod x^n)\) 假设现在多项式只有一项,显然\(B(x)\)的 ...

  10. LG4238 【【模板】多项式求逆】

    前言 学习了Great_Influence的递推实现,我给大家说一下多项式求逆严格的边界条件,因为我发现改动一些很小的边界条件都会使程序出错.怎么办,背代码吗?背代码是不可能,这辈子都不会背代码的.理 ...

随机推荐

  1. C# 文字转成声音

    C#程序要把特定的文字朗读出来,对于Windows 7及之后的系统可以使用.Net组件——System.Speech 首先在项目中添加“System.Speech”的引用: 然后大致的示例代码如下: ...

  2. laravel的model例子

    5里面直接artisan建立model ./artisan make:model MyModel 找到MyModel,改成下面这样 <?php namespace App; use Illumi ...

  3. linux下使用tar命令详解

    解压语法:tar [主选项+辅选项] 文件或者目录 使用该命令时,主选项是必须要有的,它告诉tar要做什么事情,辅选项是辅助使用的,可以选用. 主选项: c 创建新的档案文件.如果用户想备份一个目录或 ...

  4. centos7 桥接配置

    cd /etc/sysconfig/network-scripts/ 名字可能各不同,一般出现在第一个位置 vim ifcfg-ens33 然后重启 systemctl restart network ...

  5. sorl基本原理

    索引原理 场景:小时候我们都使用过新华字典,妈妈叫你翻开第38页,找到“坑爹”所在的位置,此时你会怎么查呢?毫无疑问,你的眼睛会从38页的第一个字开始从头至尾地扫描,直到找到“坑爹”二字为止.这种搜索 ...

  6. 009:JSON

    一. MySQL JSON类型 1. JSON介绍 什么是 JSON ? JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻量级 ...

  7. mongoDB的权限管理

    最近做一个关于mongoDB权限的功能, 在网上找了好久,各种命令,各种配置,各种修改,都没有解决哥的困惑.无奈,睡一觉后,灵光乍现,灵感来了. 下面就是我的最新发现,当然在各位看官的眼里,我的这个也 ...

  8. java类继承总结一 父类类型与子类类型之间的转化问题(转)

    java类继承总结一 父类类型与子类类型之间的转化问题 本文将通过一个实例描述父类类型与子类类型之间的转化问题,这个很特殊的问题常常会导致一些潜在的危险,让你整整一个晚上都在调试程序以解决一个让人抓狂 ...

  9. IDA Pro 权威指南学习笔记(九) - 数据搜索

    Search -> Next Code 命令将光标移动到下一个包含指令的位置 Jump -> Jump to Function 命令可以打开所有函数,可以迅速选择一个函数并导航到该函数所在 ...

  10. PCI、PCI-x,PCI-E兼容以及他们之间的区别详细图解

    一.PCI PCI接口分为32bit和64bit两种,32bit就是一般台式机使用的普通的pci接口(图一.图三),64bit接口比32bit接口长一些一般只出现在服务器上(图四.图五).32bit和 ...