洛谷P4238 多项式乘法逆元

模板:多项式乘法逆元

给出一个度为 n − 1 n-1 n1的多项式 f ( x ) f(x) f(x),求一个度为 n − 1 n-1 n1 g ( x ) g(x) g(x),使得 f ( x ) ⋅ g ( x ) ≡ 1   ( m o d   x n ) f(x)\cdot g(x) \equiv1\ (mod\ x^n) f(x)g(x)1 (mod xn)

这里的多项式 m o d   x k mod\ x^k mod xk的意思是舍弃掉所有次数 ≥ k \geq k k的项后的多项式

Solution:

多项式的操作似乎都是分治解决的

若我们找到一个 t ( x ) t(x) t(x),使得

f ( x ) ⋅ t ( x ) ≡ 1   ( m o d   x ⌈ n 2 ⌉ ) (1) f(x)\cdot t(x)\equiv 1\ (mod\ x^{\lceil\frac{n}{2}\rceil})\tag{1} f(x)t(x)1 (mod x2n)(1)

因为

f ( x ) ⋅ g ( x ) ≡ 1   ( m o d   x n ) f(x)\cdot g(x)\equiv1\ (mod\ x^{n}) f(x)g(x)1 (mod xn)

于是有

f ( x ) ⋅ g ( x ) ≡ 1   ( m o d   x ⌈ n 2 ⌉ ) (2) f(x)\cdot g(x)\equiv1\ (mod\ x^{\lceil\frac{n}{2}\rceil})\tag{2} f(x)g(x)1 (mod x2n)(2)

( 1 ) (1) (1)与这个式子做差,有

f ( x ) ⋅ ( t ( x ) − g ( x ) ) ≡ 0   ( m o d   x ⌈ n 2 ⌉ ) f(x)\cdot(t(x)-g(x)) \equiv0\ (mod\ x^{\lceil\frac{n}{2}\rceil}) f(x)(t(x)g(x))0 (mod x2n)

由于 f ( x ) f(x) f(x)不可能为0,于是

t ( x ) − g ( x ) ≡ 0   ( m o d   x ⌈ n 2 ⌉ ) t(x)-g(x)\equiv0\ (mod\ x^{\lceil\frac{n}{2}\rceil}) t(x)g(x)0 (mod x2n)

两边平方并移项有

g 2 ( x ) ≡ 2 ⋅ t ( x ) ⋅ g ( x ) − t 2 ( x )   ( m o d   x ⌈ n 2 ⌉ ) g^{2}(x)\equiv2\cdot t(x) \cdot g(x)-t^{2}(x)\ (mod\ x^{\lceil\frac{n}{2}\rceil}) g2(x)2t(x)g(x)t2(x) (mod x2n)

左右两边乘 f ( x ) f(x) f(x),得到

f ( x ) ⋅ g 2 ( x ) ≡ 2 ⋅ f ( x ) ⋅ t ( x ) ⋅ g ( x ) − f ( x ) ⋅ t 2 ( x )   ( m o d   x ⌈ n 2 ⌉ ) f(x)\cdot g^{2}(x)\equiv2\cdot f(x)\cdot t(x) \cdot g(x)-f(x)\cdot t^{2}(x)\ (mod\ x^{\lceil\frac{n}{2}\rceil}) f(x)g2(x)2f(x)t(x)g(x)f(x)t2(x) (mod x2n)

( 1 ) ( 2 ) (1)(2) (1)(2)两式,代入得到

g ( x ) ≡ 2 ⋅ t ( x ) − f ( x ) ⋅ t 2 ( x )   ( m o d   x ⌈ n 2 ⌉ ) (3) g(x)\equiv 2\cdot t(x)-f(x)\cdot t^{2}(x)\ (mod\ x^{\lceil\frac{n}{2}\rceil})\tag{3} g(x)2t(x)f(x)t2(x) (mod x2n)(3)

于是我们求 g ( x ) g(x) g(x)可以先求 t ( x ) t(x) t(x),求 t ( x ) t(x) t(x)可以先求 ( m o d   x ⌈ n 4 ⌉ ) (mod\ x^{\lceil\frac{n}{4}\rceil}) (mod x4n),递归出口即求 ( m o d   x ) (mod\ x) (mod x),此时只剩常数项,多项式逆元就是常数项逆元

tips:

( 3 ) (3) (3)式递推时不需要多次ntt,我们只要把他们转换为点值式后直接运算就可以了,不过需要注意的是,这里面发生了三个多项式相乘,因此相乘时 l i m i t limit limit要设为大于三个多项式的度总和的一个2的幂

// #include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
using namespace std;

using ll=long long;
const int N=270005,inf=0x3fffffff;
const long long INF=0x3f3f3f3f3f3f,mod=998244353,inv3=332748118;

int getlen(int k)
{
	int ret=0;
	while(k){ret++;k>>=1;}
	return ret;
}

int getrev(int k,int len)
{
	int ret=0;
	while(k){ret=(ret<<1|(k&1));k>>=1;len--;}
	return ret<<len;
}

ll qpow(ll a,ll b)
{
	ll ret=1,base=a;
	while(b)
	{
		if(b&1) ret=ret*base%mod;
		base=base*base%mod;
		b>>=1;
	}
	return ret;
}

ll inv(ll k){return qpow(k,mod-2);}

int pos[N];

void ntt(ll *a,int limit,int op)
{
	for(int i=0;i<limit;i++)
		if(i<pos[i]) swap(a[i],a[pos[i]]);
	for(int len=2;len<=limit;len<<=1)
	{
		ll base=qpow(op==1?3:inv3,(mod-1)/len);
		for(int l=0;l<limit;l+=len)
		{
			ll now=1;
			for(int i=l;i<l+len/2;i++)
			{
				ll x=a[i]%mod,y=now*a[i+len/2]%mod;
				a[i]=(x+y)%mod;
				a[i+len/2]=(x-y+mod)%mod;
				now=now*base%mod;
			}
		}
	}
}

ll a[N],b[N];

inline void multi(ll *f,ll* g,int n,int m)//f*=g
{
	int limit=1;
	while(limit<=n+2*m) limit<<=1;//此处式n+2*m,三个多项式相乘了
	int len=getlen(limit-1);
	for(int i=0;i<limit;i++)
	{
		pos[i]=getrev(i,len);
		a[i]=f[i]; b[i]=g[i];
	}
	ntt(a,limit,1); ntt(b,limit,1);
	for(int i=0;i<limit;i++) a[i]=b[i]*((2-a[i]*b[i]%mod)%mod+mod)%mod;
	ntt(a,limit,-1);
	ll tmp=inv(limit);
	for(int i=0;i<limit;i++) f[i]=a[i]*tmp%mod;
}

int n,nn;
ll f[N],g[N],t[N];

void solve(int len)
{
	if(len==1){t[0]=inv(f[0]);return;}
	solve(len+1>>1);//此处一定要Len/2上取整
	for(int i=0;i<n;i++) g[i]=f[i];
	multi(g,t,n,len+1>>1);
	for(int i=0;i<len;i++) t[i]=g[i];
	for(int i=len;i<n+2*(len+1>>1);i++) g[i]=t[i]=0;
}

int main()
{
	cin>>n;
	for(int i=0;i<n;i++) cin>>f[i];
	solve(n);
	for(int i=0;i<n;i++) printf("%lld ",g[i]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值