多项式求逆元详解+模板 【洛谷P4238】多项式求逆
概述
多项式求逆元是一个非常重要的知识点,许多多项式操作都需要用到该算法,包括多项式取模,除法,开跟,求ln,求exp,快速幂。用快速傅里叶变换和倍增法可以在$O(n log n)$的时间复杂度下求出一个$n$次多项式的逆元。
前置技能
快速数论变换(NTT),求一个数$x$在模$p$意义下的乘法逆元。
多项式的逆元
给定一个多项式$A(x)$,其次数为$deg_A$,若存在一个多项式$B(x)$,使其满足$deg_B≤deg_A$,且$A(x)\times B(x) \equiv 1 (mod\ x^n)$,则$B(x)$即为$A(x)$在模$x^n$意义下的的乘法逆元。
求多项式的逆元
我们不妨假设,$n=2^k,k∈N$。
若$n=1$,则$A(x)\times B(x) \equiv a_0\times b_0 \equiv 1 (mod\ x^1)$。其中$a_0$,$b_0$表示多项式$A$和多项式$B$的常数项。
若需要求出$b_0$,直接用费马小定理求出$a_0$的乘法逆元即可。
当$n>1$时:
我们假设在模$x^{\frac{n}{2}}$的意义下$A(x)$的逆元$B'(x)$我们已经求得。
依据定义,则有
$A(x)B'(x)\equiv 1 (mod\ x^{\frac{n}{2}})$ $(1)$
对$(1)$式进行移项得
$A(x)B'(x)-1\equiv 0 (mod\ x^{\frac{n}{2}})$ $(2)$
然后对$(2)$式等号两边平方,得
$A^2(x)B'^2(x)-2A(x)B'(x)+1\equiv 0(mod\ x^{n})$ $(3)$
将常数项移动到等式右侧,得
$A^2(x)B'^2(x)-2A(x)B'(x)\equiv -1(mod\ x^{n})$ $(4)$
将等式两边去相反数,得
$2A(x)B'(x)-A^2(x)B'^2(x)\equiv 1(mod\ x^{n})$ $(5)$
下面考虑回我们需要求的多项式$B(x)$,依据定义,其满足
$A(x)B(x)\equiv 1(mod\ x^{n}) $(6)$
将$(5)-(6)$并移项,得
$A(x)B(x)\equiv 2A(x)B'(x)-A^2(x)B'^2(x)(mod\ x^{n})$ $(7)$
等式两边约去$A(x)$,得
$B(x)\equiv 2B'(x)-A(x)B'^2(x)(mod\ x^{n})$ $(8)$
显然,我们可以用上述式子求出$B(x)$。
这一步的计算我们可以使用$NTT$,时间复杂度为$O(n log n)$。
我们可以通过递归的方法,求解出$B(x)$。
时间复杂度$T(n)=T(\dfrac{n}{2})+O(n log n)=O(n log n)$。
洛谷上有一道题目就叫做多项式求逆元(点这里),可以先做下那一题。
模板如下:
#include<bits/stdc++.h>
#define M (1<<19)
#define L long long
#define MOD 998244353
#define G 3
using namespace std; L pow_mod(L x,L k){
L ans=;
while(k){
if(k&) ans=ans*x%MOD;
x=x*x%MOD; k>>=;
}
return ans;
} void change(L a[],int n){
for(int i=,j=;i<n-;i++){
if(i<j) swap(a[i],a[j]);
int k=n>>;
while(j>=k) j-=k,k>>=;
j+=k;
}
}
void NTT(L a[],int n,int on){
change(a,n);
for(int h=;h<=n;h<<=){
L wn=pow_mod(G,(MOD-)/h);
for(int j=;j<n;j+=h){
L w=;
for(int k=j;k<j+(h>>);k++){
L u=a[k],t=w*a[k+(h>>)]%MOD;
a[k]=(u+t)%MOD;
a[k+(h>>)]=(u-t+MOD)%MOD;
w=w*wn%MOD;
}
}
}
if(on==-){
L inv=pow_mod(n,MOD-);
for(int i=;i<n;i++) a[i]=a[i]*inv%MOD;
reverse(a+,a+n);
}
} void getinv(L a[],L b[],int n){
if(n==){b[]=pow_mod(a[],MOD-); return;}
static L c[M],d[M];
memset(c,,n<<); memset(d,,n<<);
getinv(a,c,n>>);
for(int i=;i<n;i++) d[i]=a[i];
NTT(d,n<<,); NTT(c,n<<,);
for(int i=;i<(n<<);i++) b[i]=(*c[i]-d[i]*c[i]%MOD*c[i]%MOD+MOD)%MOD;
NTT(b,n<<,-);
for(int i=;i<n;i++) b[n+i]=;
}
L a[M]={},b[M]={};
int main(){
int n,N; scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%lld",a+i);
for(N=;N<=n;N<<=);
getinv(a,b,N);
for(int i=;i<=n;i++) printf("%lld ",b[i]);
}
多项式求逆元详解+模板 【洛谷P4238】多项式求逆的更多相关文章
- 树链剖分详解(洛谷模板 P3384)
洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...
- 【learning】多项式开根详解+模板
概述 多项式开跟是一个非常重要的知识点,许多多项式题目都要用到这一算法. 用快速数论变换,多项式求逆元和倍增法可以在$O(n log n)$的时间复杂度下求出一个$n$次多项式的开根. 前置技能 快速 ...
- 线段树入门详解,洛谷P3372 【模板】线段树 1
关于线段树: 本随笔参考例题 P3372 [模板]线段树 1 所谓线段树就是把一串数组拆分成一个一个线段形成的一棵树. 比如说像这样的一个数组1,2,3,4,5: 1 ~ 5 / ...
- 洛谷P4238【模板】多项式求逆
洛谷P4238 多项式求逆:http://blog.miskcoo.com/2015/05/polynomial-inverse 注意:直接在点值表达下做$B(x) \equiv 2B'(x) - A ...
- 【数论】卢卡斯定理模板 洛谷P3807
[数论]卢卡斯定理模板 洛谷P3807 >>>>题目 [题目] https://www.luogu.org/problemnew/show/P3807 [输入格式] 第一行一个 ...
- KMP字符串匹配 模板 洛谷 P3375
KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...
- 洛谷P1067 多项式输出 NOIP 2009 普及组 第一题
洛谷P1067 多项式输出 NOIP 2009 普及组 第一题 题目描述 一元n次多项式可用如下的表达式表示: 输入输出格式 输入格式 输入共有 2 行 第一行 1 个整数,n,表示一元多项式的次数. ...
- 高斯消元法(Gauss Elimination)【超详解&模板】
高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵.高斯消元法的原理是:若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. ...
- 【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]
以题写模板. 写了两个:n^2版本与nlogn版本 P1091 合唱队形 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队 ...
随机推荐
- 【Web】Nginx下载与安装
Nginx介绍 Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄罗 ...
- 2018.10.19 NOIP训练 变化的序列(线性dp)
传送门 f[i][j]f[i][j]f[i][j]表示后iii个对答案贡献有jjj个a的方案数. 可以发现最后a,ba,ba,b的总个数一定是n∗(n−1)/2n*(n-1)/2n∗(n−1)/2 因 ...
- 2018.09.20 atcoder Painting Graphs with AtCoDeer(tarjan+polya)
传送门 一道思维题. 如果没有环那么对答案有k的贡献. 如果恰为一个环,可以用polya求贡献. 如果是一个有多个环重叠的双联通的话,直接转化为组合数问题(可以证明只要每种颜色被选取的次数相同一定可以 ...
- gj7 对象引用、可变性和垃圾回收
7.1 python变量到底是什么 #python和java中的变量本质不一样,python的变量实质上是一个指针 int str, 便利贴 a = 1 a = "abc" #1. ...
- 用原生的javascript 实现一个无限滚动的轮播图
说一下思路:和我上一篇博客中用JQ去写的轮播图有相同点和不同点 相同点: 首先页面布局是一样的 同样是改变.inner盒子的位置去显示不同的图片 不同点: 为了实现无限滚动需要多添加两张重复的图片 左 ...
- http://localhost:8080/hello?wsdl
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-u ...
- 2015 - 4- 21 iOS开发越狱环境的搭建1
2015 - 4- 20 1. 越狱环境的搭建 http://www.iduuke.com/2030.html http://www.cnblogs.com/xiongwj0910/archi ...
- SBIT
SBIT chmod -R o+t dirs/ 给指定目录设置保护,只有所有者才能删除.
- POJ2456 Aggressive cows 2017-05-11 17:54 38人阅读 评论(0) 收藏
Aggressive cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13993 Accepted: 6775 ...
- codevs 1160
这道题还是和蛇形填数有关,因为要不停的去转圈圈去判断是否到了最中间的那个位置,所以用到了递归的思想. #include<stdio.h> int n,a[100][100]; void r ...