【Learning】 多项式的相关计算

约定的记号

  
  对于一个多项式\(A(x)\),若其最高次系数不为零的项是\(x^k\),则该多项式的次数为\(k\).
  
  记为\(deg(A)=k\).
  
  对于\(x\in(k,+ \infty)\),称\(x\)都为\(A(x)\)的次数界. 但一般地,我们都使用\(k+1\)作为\(A(x)\)的次数界
  

  
  

多项式求逆

  
  给定多项式\(A(x)\),求其在模\(x^n\)意义下的逆多项式\(B(x)\),使得
\[
\begin{equation} \label{eqn1} A(x)B(x)\equiv1 \pmod {x^n} \end{equation}
\]
  其中,\(B(x)\)的次数小于等于\(A(x)\)的次数.
  
  
  
  采用倍增思路向上倍增求解.
  
  当\(n=1\)时,\(A(x)\)与\(B(x)\)仅有一个常数项,且\(B(x)\)的常数项为\(A(x)\)常数项的逆元。多项式有无逆元也取决于这个常数是否有逆元.
  
  假设已经求得\(A(x)\)在模\(x^{\lceil\frac n 2\rceil}\)意义下的逆元\(B'(x)\)。
\[
\begin{equation} A(x)B'(x)=1 \pmod{x^{\lceil\frac n 2\rceil}} \end{equation}
\]
  而\((1)\)放在模\(x^{\lceil\frac n 2\rceil}\)意义下同样成立,有
\[
\begin{equation} \label{eqn2} A(x)B(x)\equiv1 \pmod {x^{\lceil\frac n 2\rceil}} \end{equation}
\]
?  将\((3)-(2)\)得到
\[
B(x)-B'(x)\equiv 0 \pmod {x^{\lceil\frac n 2\rceil}}
\]
  平方得到
\[
B^2(x)-2B(x)B'(x)+B'^2(x)\equiv 0 \pmod {x^n}
\]
?  模数同时平方的原因是:原本多项式模\(x^{\lceil\frac n 2\rceil}\)为0,说明\(0\)~\(\lceil\frac n 2\rceil-1\)项的系数为0,平方后由于系数相乘,这些0系数会导致0~n-1项系数为0,也即模\(x^n\)为0.
  
  两边同乘\(A(x)\),消去\(B(x)\)并移项,得到
\[
B(x) \equiv 2B'(x) - A(x)B'^2(x) \pmod {x^n}
\]
  至此可以递归倍增求解,伪代码如下,忽略清零、取模操作。
  

void polyInv(int *a,int *b,int n){ // a是要求逆元的多项式,b是在模x^n意义下的a的逆元
    if(n==1) 令b为一个次数为1,常数项为a[0]的逆元的多项式,返回;
    polyInv(a,b,(n+1)>>1);
    ntt_init(dega+degb+degb); //ntt长度
    static int A[]=a,B[]=b; //临时数组,防止影响到传入的指针
    ntt(A);
    ntt(B);
    for(int i=0;i<nttlen;i++)
        A[i]=2*B[i]-A[i]*B[i]*B[i]; //点值计算
    ntt(A,-1);
    b=A;
}

  
  时间复杂度\(O(n log n)\),不过我不知道怎么证.
  
  
  
  
  

多项式除法及取模

  
  给定多项式\(A(x)\)和多项式\(B(x)\),求两个多项式\(D(x)\)与\(R(x)\),使得
\[
\begin{equation} \label{1} A(x)=D(x)B(x)+R(x) \end{equation}
\]
  其中,\(deg(A)>=deg(B)\) , \(deg(D)\leq deg(A)-deg(B)\),\(deg(R)<deg(B)\).
  
  
  
  除法用奇妙变化解决.
  
  引入一个操作:翻转操作. 对于一个次数为\(n\)的多项式\(A(x)\),定义
\[
A^R(x)=x^nA(\frac 1 x)
\]
  会发现\(A^R(x)\)的系数相对于\(A(x)\)完全\(reverse\)了一下。
  
?  将\((4)\)的\(x\)换成\(\frac 1 x\),并两边同乘\(x^n\),记\(n=deg(A)\), \(m=deg(B)\), \(deg(D)=n-m\), \(deg(R)=m-1\).
\[
\begin{aligned}
x^nA(\frac1x)&=x^{n-m}D(\frac1x)x^mB(\frac1x)+x^{n-m+1}x^{m-1}R(\frac1x)\A^R(x)&=D^R(x)B^R(x)+x^{n-m+1}R^R(x)
\end{aligned}
\]
?  我们发现\(D^R(x)\)的次数仍然等于\(n-m\),如果把上式放在模\(x^{n-m+1}\)意义下,我们会发现\(D^R(x)\)不会受到任何影响,而\(x^{n-m+1}R^R(x)\)被完全模掉了!
  
?  于是
\[
\begin{aligned}
A^R(x)&\equiv D^R(x)B^R(x)\pmod{x^{n-m+1}}\D^R(x)&\equiv A^R(x){B^R}^{-1}(x)\pmod{x^{n-m+1}}
\end{aligned}
\]
  直接对\(A\)系数翻转,\(B\)系数翻转,求\(B\)的逆,\(A\)和\(B\)一乘,把结果的系数再次翻转,就是\(D\)了!
  

void polyDiv(int *a,int *b,int *d){// a和b对应上文的A和B,d是上文的D,是答案
    if(deg(a)<deg(b)) 令d为一个0多项式,返回;
    reverse(a);
    reverse(b);
    static int invb[];
    polyInv(b,invb,deg(b)+1); //b次数界是deg(b)+1
    d=a*invb;
    reverse(d);
}

  
  如果你还要求\(R(x)\),带回最初的式子直接算就好,多项式乘法用*直接代替了。
  

void polyMod(int *a,int *b,int *r){
    if(deg(a)<deg(b)) 令r为a,返回;
    static int d[];
    polyDiv(a,b,d);
    r=a-d*b;
}

原文地址:https://www.cnblogs.com/RogerDTZ/p/8724533.html

时间: 2024-08-10 19:14:23

【Learning】 多项式的相关计算的相关文章

圆的相关计算

package 练习; import java.awt.BorderLayout;import java.awt.Color;import java.awt.Font; import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import java.awt.GridLayout;import java.awt.TextArea;import j

mysql数据导出到excel以及相关计算

mysql 查询出数据之后, 可以选择导出文件 默认是csv文件  如果是整数类型的数据 可以CONCAT('\'', filed) 多加个'就可以变成文本了, 然后以文本编辑器打开csv文件 把'等字符替换为空字符串. 新建一个excel文件,找到数据-->自文本,选择下一步 格式为文本  确定即可 一些基本的excel函数: 计算某个字符或数字等的个数:=COUNTIF(A:A,"测试") 就是在A列的'测试'这个字符串出现的个数 根据身份证号计算性别:=IF(MOD(MID

BZOJ3684 大朋友和多叉树(多项式相关计算)

设$f(x)$为树的生成函数,即$x^i$的系数为根节点权值为$i$的树的个数.不难得出$f(x)=\sum_{k\in D}f(x)^k+x$我们要求这个多项式的第$n$项,由拉格朗日反演可得$[x^n]f(x)=\frac1n[x^{n-1}](\frac x{g(x)})^n$其中$[x^n]f(x)$表示$f(x)$的$n$次项系数.$f(x)$是$g(x)$的复合逆,即$g(f(x))=x$在本题中,$g(x)=x-\sum_{k\in D}x^k$我们需要多项式求逆和多项式快速幂.多

多项式FFT相关模板

自己码了一个模板...有点辛苦...常数十分大,小心使用 #include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <algorithm> #include <vector> using namespace std; #de

二进制的原码、反码、补码及相关计算

1.二进制的最高位是符号位,0表示正数,1表示负数2.正数的原码.反码.补码都一样3.负数的反码=它原码符号位不变,其他位取反(0->1,1->0)4.负数的补码=它的反码+15.0的反码.补码.都是06.php没有无符号数,就是说php中的都是有符号的7.在计算机运算的时候都是以补码的方式来运行的 1 如: 2 以下实例都以4个字节举例说明 3 1 ---->原码 00000000 00000000 00000000 00000001 4 1 ---->反码 00000000 0

7.3 编址与存储相关计算

两个方面的内容:一方面是内存的编址方法,另外一方面就是磁带.光盘它的容量以及其它方面的一些计算.内存编址方法这一块有两个方面的内容是需要大家掌握的:第一方面是编址, 编址的概念:在计算机的系统当中,它的存储器有很多个存储空间,就如同我们去一个澡堂,它可能有储物柜,然后排列了很多很多的储物柜,它会对这个储物柜进行编号,从1号开始编一直编到100号或者是200号,如果说你不对这些储物柜进行编号,那么这些储物柜就无法利用起来.因为客人来了之后他不清楚自己是哪一个储物柜,所以不方便把东西放进来也不方便把

黑马程序员——java基础——负整数相关计算及其原因

-----------android培训.java培训.java学习型技术博客.期待与您交流!------------ 时间—— 2016年1月6日15:33:02 1.整数类取值范围及其分析? 我们知道整形的取值范围为-2^31-2^31-1,但是我就很纳闷为什么负数哪里没有减1,而整数这里却减1.在加上左边可以利用等差数列计算出来其最大值的确是2^31-1.可是我去计算负数的时候,纳闷了.我们知道正负数的符号位就是第三十一位,而往往符号位是不参与运算的.有些朋友可能会说,1000000000

地图坐标相关计算

总结的一些地图坐标计算方法,包括: 地球坐标.百度坐标.火星坐标相互转换两点坐标距离计算根据坐标及半径求坐标范围(附近的XXX功能)package com.thon.commons.utils; import java.text.DecimalFormat; /** * @ClassName: MapUtil * @author: SuperZemo * @email: [email protected] * @Date 10/21/14 14:21 * @Description 地图工具类 *

球面三角的相关计算

已知3个球心角(A0.B0.C0)及球体半径R,计算:球面三角的角度(A.B.C).球面三角的面积.以及球角锥的体积 (涉及角度均为弧度制) 1.计算球面三角形的边长a.b.c: a = A0*R; (弧长=弧度*球半径) b = B0*R; c = C0*R; 2.计算球面角: (1)方法一:基于余弦定理求解: 故,A = acos( (cosa-cosbcosc)/(sinbsinc)),同理可计算球面角B和C (2)方法二,也可有正弦公式求得 3.计算球面超(spherical exces