题目链接

多项式除法 & 取模

  很神奇,记录一下。

  只是主要部分,更详细的和其它内容看这吧。

  给定一个\(n\)次多项式\(A(x)\)和\(m\)次多项式\(D(x)\),求\(deg(Q)\leq n-m\)的多项式\(Q(x)\),满足$$A(x)=D(x)\times Q(x)+R(x)$$

  其中\(R(x)\)可以看做是\(m-1\)次多项式(不足\(m-1\)次系数补\(0\))。

  首先是想消除\(R(x)\)的影响。

  对于一个\(n\)次多项式\(A(x)\),记$$AR(x)=xnA(\frac{1}{x})$$

  例如\(A(x)=2x^3+4x^2-3x+1\),那么把\(\frac{1}{x}\)代进去,再乘个\(x^n\),可得$$AR(x)=x3-3x^2+4x+2$$

  相当于将\(A(x)\)的系数进行了反转。

  现在把\(A(x)=D(x)\times Q(x)+R(x)\)的\(x\)替换成\(\frac{1}{x}\),再乘\(x^n\),得

\[x^nA(\frac{1}{x})=x^{m}D(\frac{1}{x})x^{n-m}Q(\frac{1}{x})+x^{n-m+1}x^{m-1}R(x)$$ $$A^R(x)=D^R(x)Q^R(x)+x^{n-m+1}R^R(x)
\]

  要求\(Q(x)\),反转后次数仍不超过\(n-m\),而\(x^{n-m+1}R^R(x)\)最低项的次数\(>n-m\)。于是我们把式子放在模\(x^{n-m+1}\)意义下,\(R(x)\)就被消除了,且不影响\(Q(x)\)。而\(A(x),D(x)\)是已知的,不会有问题。

  即$$A^R(x)\equiv D^R(x)\times QR(x) (mod x{n-m+1})$$

  对\(D^R(x)\)求逆元,乘\(A^R(x)\)后可以得到\(Q^R(x)\),系数反转后即得\(Q(x)\)。\(A(x)-D(x)\times Q(x)\)就可以得到\(R(x)\)了。即多项式取模也可以这么做。

  复杂度\(\mathcal O(n\log n)\)。

  1. //640ms 7.55MB
  2. #include <cstdio>
  3. #include <cctype>
  4. #include <cstring>
  5. #include <algorithm>
  6. #define P (998244353)
  7. #define Rt (3)
  8. #define i_Rt (332748118)
  9. #define Mul(a,b) (1ll*a*b%P)
  10. #define Sub(a,b) (a<b ? a-b+P : a-b)
  11. #define Clear() memset(A,0,sizeof A),memset(B,0,sizeof B)
  12. //#define gc() getchar()
  13. #define MAXIN 200000
  14. #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
  15. const int N=(1<<18)+5;
  16. int n,m,F[N],D[N],invD[N],Q[N],A[N],B[N],tmp[N],rev[N],W[N];//F = divisor * quotient + remainder
  17. char IN[MAXIN],*SS=IN,*TT=IN;
  18. inline int read()
  19. {
  20. int now=0;register char c=gc();
  21. for(;!isdigit(c);c=gc());
  22. for(;isdigit(c);now=now*10+c-'0',c=gc());
  23. return now;
  24. }
  25. inline int FP(int x,int k)
  26. {
  27. int t=1;
  28. for(; k; k>>=1, x=Mul(x,x))
  29. if(k&1) t=Mul(x,t);
  30. return t;
  31. }
  32. inline int Get_len(int x)
  33. {
  34. int len=1; while(len<=x) len<<=1;
  35. return len;
  36. }
  37. void NTT(int *a,int len,int type)//polynomial
  38. {
  39. int lim=1, L=0;
  40. while(lim<len) lim<<=1, ++L;
  41. for(int i=1; i<lim; ++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<L-1);
  42. for(int i=1; i<lim; ++i) if(i<rev[i]) std::swap(a[i],a[rev[i]]);
  43. for(int i=2; i<=lim; i<<=1)
  44. {
  45. int mid=i>>1, Wn=FP(~type?Rt:i_Rt,(P-1)/i), t;//次数:(P-1)/i!
  46. W[0]=1;
  47. for(int j=1; j<mid; ++j) W[j]=Mul(W[j-1],Wn);
  48. for(int j=0; j<lim; j+=i)
  49. for(int k=0; k<mid; ++k)
  50. a[j+k+mid]=(a[j+k]-(t=Mul(a[j+k+mid],W[k]))+P)%P,
  51. a[j+k]=(a[j+k]+t)%P;
  52. }
  53. if(type==-1)
  54. for(int i=0,inv=FP(lim,P-2); i<lim; ++i) a[i]=Mul(a[i],inv);
  55. }
  56. void P_Inv(int *f,int *g,int len)//len:要求逆元的长度
  57. {
  58. if(len==1) {g[0]=FP(f[0],P-2); return;}
  59. P_Inv(f,g,len>>1);
  60. for(int i=0; i<len; ++i) A[i]=f[i], B[i]=g[i];
  61. NTT(A,len<<1,1), NTT(B,len<<1,1);
  62. for(int i=0; i<len<<1; ++i) A[i]=Mul(A[i],Mul(B[i],B[i]));
  63. NTT(A,len<<1,-1);
  64. for(int i=0; i<len; ++i) g[i]=((g[i]<<1)%P-A[i]+P)%P;
  65. }
  66. void P_Mul(int *a,int *b,int *res,int l1,int l2)
  67. {
  68. int len=Get_len(l1+l2);
  69. Clear();
  70. for(int i=0; i<=l1; ++i) A[i]=a[i];
  71. for(int i=0; i<=l2; ++i) B[i]=b[i];
  72. NTT(A,len,1), NTT(B,len,1);
  73. for(int i=0; i<len; ++i) res[i]=Mul(A[i],B[i]);
  74. NTT(res,len,-1);
  75. }
  76. int main()
  77. {
  78. n=read(),m=read();
  79. for(int i=0; i<=n; ++i) F[i]=read();
  80. for(int i=0; i<=m; ++i) D[i]=read();
  81. std::reverse(F,F+n+1), std::reverse(D,D+m+1);
  82. P_Inv(D,invD,Get_len(n-m));
  83. P_Mul(F,invD,Q,n-m,n-m);//次数都是n-m (mod x^{n-m+1})
  84. std::reverse(Q,Q+n-m+1);
  85. for(int i=0; i<=n-m; ++i) printf("%d ",Q[i]); putchar('\n');
  86. std::reverse(F,F+n+1), std::reverse(D,D+m+1);
  87. P_Mul(D,Q,tmp,m,n-m);
  88. for(int i=0; i<m; ++i) printf("%d ",Sub(F[i],tmp[i]));
  89. return 0;
  90. }

洛谷.4512.[模板]多项式除法(NTT)的更多相关文章

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

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

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

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

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

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

  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. 洛谷.4721.[模板]分治FFT(NTT)

    题目链接 换一下形式:\[f_i=\sum_{j=0}^{i-1}f_jg_{i-j}\] 然后就是分治FFT模板了\[f_{i,i\in[mid+1,r]}=\sum_{j=l}^{mid}f_jg ...

  6. 洛谷.4245.[模板]任意模数NTT(MTT/三模数NTT)

    题目链接 三模数\(NTT\): 就是多模数\(NTT\)最后\(CRT\)一下...下面两篇讲的都挺明白的. https://blog.csdn.net/kscla/article/details/ ...

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

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

  8. 洛谷 P4245 [模板]任意模数NTT —— 三模数NTT / 拆系数FFT(MTT)

    题目:https://www.luogu.org/problemnew/show/P4245 用三模数NTT做,需要注意时间和细节: 注意各种地方要取模!传入 upt() 里面的数一定要不超过2倍 m ...

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

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

随机推荐

  1. 利用Object.defineProperty 简化 Chrome插件本地存储操作

    通常谷歌插件本地存储写法很别扭☹,如 chrome.storage.sync.get(null,function(data){ //todo console.log(data); });  如果get ...

  2. [转]caffe中solver.prototxt参数说明

    https://www.cnblogs.com/denny402/p/5074049.html solver算是caffe的核心的核心,它协调着整个模型的运作.caffe程序运行必带的一个参数就是so ...

  3. 80.YCrCb - YUV - RGB之间的介绍

    一,引言 YUV(亦称YCrCb)是被欧洲电视系统所采用的一种颜色编码方法(属于PAL).YUV主要用于优化彩色视频信号的传输,使其向后兼容老式黑白电视.与RGB视频信号传输相比,它最大的优点在于只需 ...

  4. gcc -O0 -O1 -O2 -O3 四级优化选项及每级分别做什么优化【转】

    转自:http://blog.csdn.net/qinrenzhi/article/details/78334677 相关博客http://blog.chinaunix.net/uid-2495495 ...

  5. Python基础之多线程事件Event

    import threading,time class Boss(threading.Thread): def run(self): print("BOSS:伙计们今晚上加班到22:00&q ...

  6. jQuery UI 给button添加ID

    $("#addOrEditApp").dialog({ modal: true ,maxHeight:dialogHeight,width:dialog_width,title: ...

  7. SQLAlchemy-对象关系教程ORM-query

    一:对象关系教程查询 一个 Query创建对象时使用 Session的query()方法 .此函数接受一个变量数量的参数,可以是任何类和class-instrumented描述符的组合. Query返 ...

  8. java 内部类可以被覆盖吗

    如果创建了一个内部类,然后继承其外围类并重新定义内部类时,"覆盖"内部类就好像是其外围类的一个方法,并不起作用, 这两个内部类是完全独立的两个实体,各自在自己的命名空间内 //: ...

  9. python 多线程删除MySQL表

    一.需求分析 在<python 统计MySQL表信息>这篇博客中,链接如下: https://www.cnblogs.com/xiao987334176/p/9901692.html 已经 ...

  10. Shell学习笔记:#*、%*字符串掐头去尾方法

    一.语法 在shell中可以通过#.%对字符串进行掐头去尾操作,使用方法如下: # 表示掐头 % 表示去尾 单个#或%表示最小匹配 双个$或%表示最大匹配  二.例子1 假设我们定义一个变量为: fi ...