多项式乘法逆元 java_多项式乘法逆

本文介绍了如何利用快速傅里叶变换(NTT)算法求解多项式乘法逆元的问题。通过递归倍增方法,结合模运算,给出Java代码实现,用于找到满足( F(x) * G(x) equiv 1 ( mathrm{mod:} x^n ) )条件的多项式( G(x) )。算法首先从单一项的逆元开始,然后通过平方和移位操作逐步构建完整多项式的逆元。
摘要由CSDN通过智能技术生成

给定一个多项式 \(F(x)\) ,请求出一个多项式 \(G(x)\), 满足 \(F(x) * G(x) \equiv 1 ( \mathrm{mod\:} x^n )\)。系数对 \(998244353\) 取模。

考虑倍增

多项式只有一项时就是乘法逆元

假设我们现在得到了

\[G^{'}(x) \equiv F(x) (mod\ x^{\frac{n}{2}})

\]

我们需要求

\[G(x)\equiv F(x) (mod\ x^n)

\]

很明显

\[G(x)-G^{'}(x)\equiv 0 (mod\ x^{\frac{n}{2}})

\]

两边同时平方

\[G(x)^2-2*G(x)G^{'}(x)+G^{'}(x)\equiv 0 (mod\ x^n)

\]

两边同时乘\(F(x)\)得到

\[F(x)(G(x)^2-2*G(x)G^{'}(x)+G^{'}(x))\equiv 0 (mod\ x^n)

\]

由于

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

\]

所以

\[G(x)-2G(x)^{'}+F(x)G^{'2}(x)\equiv (mod\ x^n)

\]

移下项

\[G(x)\equiv 2G(x)^{'}-F(x)G^{'2}(x)(mod\ x^n)

\]

只要初始设置\(G(0)=F(0)^{-1}\)就可以倍增啦~

额额额不知道有没有人和我有一样的疑惑:为啥递归一次多项式次数少一半,原因是模掉了……

#include

using namespace std;

namespace red{

#define int long long

#define eps (1e-8)

inline int read()

{

int x=0;char ch,f=1;

for(ch=getchar();(ch'9')&&ch!='-';ch=getchar());

if(ch=='-') f=0,ch=getchar();

while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}

return f?x:-x;

}

const int N=5e5+10,p=998244353,g=3,gi=332748118;

int n;

int a[N],b[N],c[N];

int pos[N];

inline int fast(int x,int k)

{

int ret=1;

while(k)

{

if(k&1) ret=ret*x%p;

x=x*x%p;

k>>=1;

}

return ret;

}

inline void ntt(int limit,int *a,int inv)

{

for(int i=0;i

if(i

for(int mid=1;mid

{

int Wn=fast(g,(p-1)/(mid<<1));

for(int r=mid<<1,j=0;j

{

int w=1;

for(int k=0;k

{

int x=a[j+k],y=w*a[j+k+mid]%p;

a[j+k]=x+y;

if(a[j+k]>=p) a[j+k]-=p;

a[j+k+mid]=x-y;

if(a[j+k+mid]<0) a[j+k+mid]+=p;

}

}

}

if(inv) return;

inv=fast(limit,p-2);reverse(a+1,a+limit);

for(int i=0;i

}

inline void poly_inv(int pw,int *a,int *b)

{

if(pw==1) {b[0]=fast(a[0],p-2);return;}

poly_inv((pw+1)>>1,a,b);

int len=0,limit=1;

while(limit

for(int i=1;i>1]>>1)|((i&1)<

for(int i=0;i

for(int i=pw;i

ntt(limit,c,1);ntt(limit,b,1);

for(int i=0;i

ntt(limit,b,0);

for(int i=pw;i

}

inline void main()

{

n=read();

for(int i=0;i

poly_inv(n,a,b);

for(int i=0;i

}

}

signed main()

{

red::main();

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值