码迷,mamicode.com
首页 > 其他好文 > 详细

【模板】多项式求逆

时间:2019-02-04 14:12:55      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:def   nlog   pen   lin   class   etc   main   show   string   

题目描述

题解:

多项式$O(nlogn)$全家桶里面比较简单比较基础的一个。

考虑到已知$F(x)$我们要求$G(x)$满足$F(x)*G(x)=1(mod x^k)$,

首先,当$k==1$时,求一下$F(0)$逆元即可。

然后看看$mod x^k$能不能从$mod x^{k/2}$搞出来。

假设有$F(x)*H(x)=1(mod x^{k/2})$

那么$G(x)-H(x)=0(mod x^{k/2})$

平方,有$G^{2}(x)+H^{2}(x)-2*G(x)*H(x)=0(mod x^k)$

乘个$F$,有$G(x)+F(x)*H^{2}(x)-2*H(x)=0(mod x^k)$

剩下的递归。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MOD = 998244353;
const int N = 100050;
typedef long long ll;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){c=c*10+ch-0;ch=getchar();}
    x = f*c;
}
struct node
{
    int len;
    ll s[N];
    node(){memset(s,0,sizeof(s));}
    void print(int n)
    {
        for(int i=0;i<n;i++)printf("%d ",s[i]);
        puts("");
    }
}las,now;
ll fastpow(ll x,int y)
{
    ll ret = 1;
    while(y)
    {
        if(y&1)ret=ret*x%MOD;
        x=x*x%MOD;
        y>>=1;
    }
    return ret;
}
int to[4*N],lim,L;
ll inv,W[4*N];
void ntt(ll *a,int len,int k)
{
    for(int i=0;i<len;i++)
        if(i<to[i])swap(a[i],a[to[i]]);
    for(int i=1;i<len;i<<=1)
    {
        ll w0 = W[i];
        for(int j=0;j<len;j+=(i<<1))
        {
            ll w=1;
            for(int o=0;o<i;o++,w=w*w0%MOD)
            {
                ll w1 = a[j+o],w2 = a[j+o+i]*w%MOD;
                a[j+o] = (w1+w2)%MOD;
                a[j+o+i] = (w1-w2+MOD)%MOD;
            }
        }
    }
    if(k==-1)
    {
        for(int i=1;i<(len>>1);i++)swap(a[i],a[len-i]);
        for(int i=0;i<len;i++)a[i]=a[i]*inv%MOD;
    }
}
int n;
ll f[N],a[4*N],b[4*N],c[4*N];
void get_B(int dep)
{
    if(dep==1)
    {
        now.len=1;
        now.s[0]=fastpow(f[0],MOD-2);
        las = now;
        return ;
    }
    int nxt = (dep+1)/2;
    get_B(nxt);
    lim=1,L=0;
    while(lim<2*dep)lim<<=1,L++;
    for(int i=1;i<lim;i++)to[i]=((to[i>>1]>>1)|((i&1)<<(L-1)));
    inv = fastpow(lim,MOD-2);
    for(int i=1;i<lim;i<<=1)W[i]=fastpow(3,(MOD-1)/(i<<1));
    for(int i=0;i<lim;i++)a[i]=b[i]=0;
    for(int i=0;i<dep;i++)a[i]=f[i];
    for(int i=0;i<nxt;i++)b[i]=las.s[i];
    ntt(a,lim,1),ntt(b,lim,1);
    for(int i=0;i<lim;i++)c[i]=a[i]*b[i]%MOD*b[i]%MOD;
    ntt(c,lim,-1);
    now.len=dep;
    for(int i=0;i<dep;i++)now.s[i]=(2*las.s[i]-c[i]+MOD)%MOD;
    las = now;
}
int main()
{
    read(n);
    for(int i=0;i<n;i++)read(f[i]);
    get_B(n);
    now.print(n);
    return 0;
}

 

【模板】多项式求逆

标签:def   nlog   pen   lin   class   etc   main   show   string   

原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10351698.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!