• Luogu4238 【模板】多项式求逆(NTT)


      http://blog.miskcoo.com/2015/05/polynomial-inverse 好神啊!

      B(x)=B'(x)·(2-A(x)B'(x))

      注意ntt的时候防止项数溢出,即将多项式补零成n位后,相乘时次数最高的非零项不超过n次。

      upd:可以在点值表示下直接相乘。又好写又跑得快。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 550000
    #define P 998244353
    int n,t,r[N],a[N],b[N],c[N],d[N];
    int ksm(int a,int k)
    {
        if (k==0) return 1;
        int tmp=ksm(a,k>>1);
        if (k&1) return 1ll*tmp*tmp%P*a%P;
        else return 1ll*tmp*tmp%P;
    }
    int inv(int x){return ksm(x,P-2);}
    void DFT(int n,int *a,int p)
    {
        for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
        for (int i=2;i<=n;i<<=1)
        {
            int wn=ksm(p,(P-1)/i);
            for (int j=0;j<n;j+=i)
            {
                int w=1;
                for (int k=j;k<j+(i>>1);k++,w=1ll*w*wn%P)
                {
                    int x=a[k],y=1ll*w*a[k+(i>>1)]%P;
                    a[k]=(x+y)%P,a[k+(i>>1)]=(x-y+P)%P;
                }
            }
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("inverse.in","r",stdin);
        freopen("inverse.out","w",stdout);
        const char LL[]="%I64d";
    #else
        const char LL[]="%lld";
    #endif
        n=read();
        for (int i=0;i<n;i++) a[i]=read();
        t=1;b[0]=inv(a[0]);
        int inv3=inv(3);
        while (t<n)
        {
            t<<=1;
            for (int i=0;i<t;i++) d[i]=a[i];
            t<<=1;
            memcpy(c,b,sizeof(b));
            for (int i=0;i<t;i++) r[i]=(r[i>>1]>>1)|(i&1)*(t>>1);
            DFT(t,c,3);DFT(t,d,3);
            for (int i=0;i<t;i++) c[i]=1ll*c[i]*d[i]%P;
            DFT(t,c,inv3);
            int invt=inv(t);
            for (int i=0;i<t;i++) c[i]=1ll*c[i]*invt%P;
            for (int i=0;i<t;i++) c[i]=(P-c[i])%P;
            c[0]=(c[0]+2)%P;
            for (int i=(t>>1);i<t;i++) c[i]=0;
            DFT(t,b,3);DFT(t,c,3);
            for (int i=0;i<t;i++) b[i]=1ll*b[i]*c[i]%P;
            DFT(t,b,inv3);
            for (int i=0;i<t;i++) b[i]=1ll*b[i]*invt%P;
            for (int i=(t>>1);i<t;i++) b[i]=0;
            t>>=1;
        }
        for (int i=0;i<n;i++) printf("%d ",b[i]);
        return 0;
    }
  • 相关阅读:
    什么是线程池?
    线程包括哪些状态?状态之间是如何变化的?
    C语言中的文本流与二进制流的区别
    Windows+IIS结合LVS+Keepalived是实现Linux负载均衡软件
    Linux中的lo回环接口详细介绍
    Keepalived原理与实战精讲
    分布式文件系统MFS(moosefs)实现存储共享(第二版)
    C语言缓冲区(缓存)详解
    Android如何防止apk程序被反编译
    Android APK反编译详解(附图)
  • 原文地址:https://www.cnblogs.com/Gloid/p/9436474.html
Copyright © 2020-2023  润新知