题目大意:给你$n$项多项式$A(x)$,求出$B(x)$满足$B^2(x)\equiv A(x)\pmod{x^n}$

题解:考虑已经求出$B_0(x)$满足$B_0^2(x)\equiv A(x)\pmod{x^{\lceil\frac n 2\rceil}}$
$$
B(x)-B_0(x)\equiv0\pmod{x^{\lceil\frac n 2\rceil}}\\
B^2(x)−2B(x)B_0(x)+B_0^2(x)≡0\pmod{x^n}\\
A(x)-2B(x)B_0(x)+B_0^2(x)≡0\pmod{x^n}\\
B(x)\equiv\dfrac{A(x)+B_0^2(x)}{2B_0(x)}\pmod{x^n}\\
$$


update:(2019-2-10)

$$
B(x)\equiv\dfrac{A(x)+B_0^2(x)}{2B_0(x)}\pmod{x^n}\\
B(x)\equiv\dfrac{A(x)}{2B_0(x)}+\dfrac{B_0(x)}2\pmod{x^n}\\
$$
发现$\dfrac{B_0(x)}2$只会影响$B(x)$数组的前半部分(即$\pmod{x^{\lceil\frac n2\rceil}}$的部分),但是$B(x)\equiv B_0(x)\pmod{x^{\lceil\frac n2\rceil}}$,所以可以不做考虑,直接把$B_0(x)$拉过来

卡点:求$INV$时注意清空数组,防止因为$B$数组不干净导致出锅

C++ Code:

  1. #include <algorithm>
  2. #include <cctype>
  3. #include <cstdio>
  4. #define maxn 262144
  5. const int mod = 998244353, __2 = mod + 1 >> 1;
  6.  
  7. namespace std {
  8. struct istream {
  9. #define M (1 << 21 | 3)
  10. char buf[M], *ch = buf - 1;
  11. inline istream() { fread(buf, 1, M, stdin); }
  12. inline istream& operator >> (int &x) {
  13. while (isspace(*++ch));
  14. for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
  15. return *this;
  16. }
  17. #undef M
  18. } cin;
  19. struct ostream {
  20. #define M (1 << 21 | 3)
  21. char buf[M], *ch = buf - 1;
  22. inline ostream& operator << (int x) {
  23. if (!x) {*++ch = '0'; return *this;}
  24. static int S[20], *top; top = S;
  25. while (x) {*++top = x % 10 ^ 48; x /= 10;}
  26. for (; top != S; --top) *++ch = *top;
  27. return *this;
  28. }
  29. inline ostream& operator << (const char x) {*++ch = x; return *this;}
  30. inline ~ostream() { fwrite(buf, 1, ch - buf + 1, stdout); }
  31. #undef M
  32. } cout;
  33. }
  34.  
  35. namespace Math {
  36. inline int pw(int base, int p) {
  37. static int res;
  38. for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod;
  39. return res;
  40. }
  41. inline int inv(int x) { return pw(x, mod - 2); }
  42. }
  43.  
  44. inline void reduce(int &x) { x += x >> 31 & mod; }
  45. inline void clear(register int *l, const int *r) {
  46. if (l >= r) return ;
  47. while (l != r) *l++ = 0;
  48. }
  49.  
  50. namespace Poly {
  51. #define N maxn
  52. int lim, s, rev[N];
  53. int Wn[N + 1];
  54.  
  55. inline void init(const int n) {
  56. lim = 1, s = -1; while (lim < n) lim <<= 1, ++s;
  57. for (register int i = 1; i < lim; ++i) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s;
  58. const int t = Math::pw(3, (mod - 1) / lim);
  59. *Wn = 1; for (register int *i = Wn; i != Wn + lim; ++i) *(i + 1) = static_cast<long long> (*i) * t % mod;
  60. }
  61. inline void FFT(int *A, const int op = 1) {
  62. for (register int i = 1; i < lim; ++i) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
  63. for (register int mid = 1; mid < lim; mid <<= 1) {
  64. const int t = lim / mid >> 1;
  65. for (register int i = 0; i < lim; i += mid << 1)
  66. for (register int j = 0; j < mid; ++j) {
  67. const int X = A[i + j], Y = static_cast<long long> (A[i + j + mid]) * Wn[t * j] % mod;
  68. reduce(A[i + j] += Y - mod), reduce(A[i + j + mid] = X - Y);
  69. }
  70. }
  71. if (!op) {
  72. const int ilim = Math::inv(lim);
  73. for (register int *i = A; i != A + lim; ++i) *i = static_cast<long long> (*i) * ilim % mod;
  74. std::reverse(A + 1, A + lim);
  75. }
  76. }
  77.  
  78. void INV(int *A, int *B, int n) {
  79. if (n == 1) { *B = Math::inv(*A); return ; }
  80. const int len = n + 1 >> 1;
  81. INV(A, B, len); init(len * 3);
  82. static int C[N], D[N];
  83. std::copy(A, A + n, C); clear(C + n, C + lim);
  84. std::copy(B, B + len, D); clear(D + len, D + lim);
  85. FFT(D), FFT(C);
  86. for (register int i = 0; i < lim; ++i) D[i] = (2 - static_cast<long long> (D[i]) * C[i] % mod + mod) * D[i] % mod;
  87. FFT(D, 0); std::copy(D + len, D + n, B + len);
  88. }
  89. void SQRT(int *A, int *B, int n) {
  90. if (n == 1) { *B = 1; return ; }
  91. static int C[N], D[N];
  92. const int len = n + 1 >> 1;
  93. SQRT(A, B, len);
  94. INV(B, D, n), clear(D + n, D + lim);
  95. std::copy(A, A + n, C); clear(C + n, C + lim);
  96. FFT(C), FFT(D);
  97. for (register int i = 0; i < lim; ++i) D[i] = static_cast<long long> (C[i]) * D[i] % mod * __2 % mod;
  98. FFT(D, 0); std::copy(D + len, D + n, B + len);
  99. }
  100. #undef N
  101. }
  102.  
  103. int n, A[maxn], B[maxn];
  104. int main() {
  105. std::cin >> n;
  106. for (int i = 0; i < n; ++i) std::cin >> A[i];
  107. Poly::SQRT(A, B, n);
  108. for (int i = 0; i < n; ++i) std::cout << B[i] << ' ';
  109. std::cout << '\n';
  110. return 0;
  111. }

  

[洛谷P5205]【模板】多项式开根的更多相关文章

  1. 洛谷.3803.[模板]多项式乘法(FFT)

    题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. 5.4 又看了一遍,这个也不错. 2019.3.7 叕看了一遍,推荐这个. #inclu ...

  2. 洛谷.3803.[模板]多项式乘法(NTT)

    题目链接:洛谷.LOJ. 为什么和那些差那么多啊.. 在这里记一下原根 Definition 阶 若\(a,p\)互质,且\(p>1\),我们称使\(a^n\equiv 1\ (mod\ p)\ ...

  3. 洛谷.4512.[模板]多项式除法(NTT)

    题目链接 多项式除法 & 取模 很神奇,记录一下. 只是主要部分,更详细的和其它内容看这吧. 给定一个\(n\)次多项式\(A(x)\)和\(m\)次多项式\(D(x)\),求\(deg(Q) ...

  4. 洛谷.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\ ...

  5. 洛谷 P4512 [模板] 多项式除法

    题目:https://www.luogu.org/problemnew/show/P4512 看博客:https://www.cnblogs.com/owenyu/p/6724611.html htt ...

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

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

  7. 洛谷P2293 高精开根

    锣鼓2293 写完了放代码 应该没什么思维难度 ———————————————————————————————————————————————————————— python真香 m=input() ...

  8. P5277 【模板】多项式开根(加强版)(bsgs or Cipolla)

    题面 传送门 题解 首先你得会多项式开根->这里 其次你得会解形如 \[x^2\equiv a \pmod{p}\] 的方程 这里有两种方法,一个是\(bsgs\)(这里),还有一种是\(Cip ...

  9. FFT模板 生成函数 原根 多项式求逆 多项式开根

    FFT #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> ...

  10. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

随机推荐

  1. PHP中array_reduce()使用

    array_reduce — 用回调函数迭代地将数组简化为单一的值 给定一个数组: $ar = array(1,2,3,4,5); 如果要求得这个数组中各个元素之和. 方法一. 很自然的用foreac ...

  2. 使用apache cgi运行ruby脚本

    在ubuntu下 进入 /usr/lib/cgi-bin目录 新建文件 ruby.cgi 内容如下 #!/usr/bin/ruby print "Content-type: text/htm ...

  3. Qt-QML-Slider-滑块-Style

    感觉滑块这个东西,可以算是一个基本模块了,在我的项目中也有这个模块,今天我将学一下一下滑块的使用以及美化工作. 想学习滑块,那就要先建立一个滑块,新建工程什么的这里就省略了,不会的可以看我前面的几篇文 ...

  4. HTTP基本定义

    一.网络的简单定义: 1.http:是www服务器传输超文本向本地浏览器的传输协议.(应用层) 2.IP:是计算机之间相互识别通信的机制.(网络层) 3.TCP:是应用层通信之间通信.(传输层) IP ...

  5. android自动化のadb常用命令(不定期更新)

    1. adb devices 执行结果是adb为每一个设备输出以下状态信息:序列号(serialNumber) — 由adb创建的使用控制台端口号的用于唯一标识一个模拟器或手机设备的字符串,格式是 & ...

  6. JAVA Map 之元素定位,冲突碰撞

    基本特性: 维持健值对的集合接口,健不可以重复,每一个健只能映射到一个值. Map替代了原来的虚拟类Directory. Map提供了三种集合视角,keys(KeySet),values(Values ...

  7. Python爬虫使用浏览器的cookies:browsercookie

    很多用Python的人可能都写过网络爬虫,自动化获取网络数据确实是一件令人愉悦的事情,而Python很好的帮助我们达到这种愉悦.然而,爬虫经常要碰到各种登录.验证的阻挠,让人灰心丧气(网站:天天碰到各 ...

  8. C 判断成绩是否及格

    #include <stdio.h> int main(int argc, char **argv) { // 新建两个变量  pass代表及格分数的固定变量 score代表学生成绩的一个 ...

  9. Struts2(九.利用layer组件实现图片显示功能)

    1.layer前端组件介绍 layer是一款口碑极佳的web弹层组件,她具备全方位的解决方案,致力于服务各个水平段的开发人员,您的页面会轻松地拥有丰富而友好的操作体验. http://sentsin. ...

  10. 腾讯云ubuntu安装使用MySQL

    安装步骤 ubuntu@VM---ubuntu:~$ sudo apt-get install mysql-server (密码: root/root) ubuntu@VM---ubuntu:~$ s ...