• 多项式除法&取模


    除法&取模
    设 $n$ 次多项式 $F(x)$ 和 $m$ 次多项式 $G(x)$ ,求 $n-m$ 次多项式 $Q(x)$ 和 $m-1$ 次多项式 $R(x)$ 满足$$F(x)=G(x)Q(x)+R(x)$$
    于是我们有 $$F(frac{1}{x})=G(frac{1}{x})Q(frac{1}{x})+R(frac{1}{x})$$
    两遍同乘 $x^n$ : $$x^nF(frac{1}{x})=x^mG(frac{1}{x})x^{n-m}Q(frac{1}{x})+x^{n-m+1}x^{m-1}R(frac{1}{x})$$
    对于 $n$ 次多项式 $A(x)$ , $x^nA(frac{1}{x})$ 代表的是多项式系数对称交换,设其为 $a(x)$,则$$f(x)=g(x)q(x)+x^{n-m+1}r(x)$$
    由于 $Q(x)$ 是 $n-m$ 次多项式,于是式子满足$$f(x)equiv g(x)q(x) pmod{x^{n-m+1}}$$
    于是$$q(x)equiv frac{f(x)}{g(x)} pmod{x^{n-m+1}}$$
    多项式求逆即可
    于是我们可以求出 $Q(x)$ ,根据定义求出 $R(x)$ 即可

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=6e5+5,P=998244353;
    int n,m,f[N],g[N],G[2]={3,(P+1)/3},A[N],B[N],t,p,re[N],d[N],q[N];
    int X(int x){return x>=P?x-P:x;}
    int K(int x,int y){
        int z=1;
        for (;y;y>>=1,x=1ll*x*x%P)
            if (y&1) z=1ll*z*x%P;
        return z;
    }
    void put(int *a,int l){
        for (int i=0;i<=l;i++)
            printf("%d",a[i]),
            putchar(i<l?' ':'
    ');
    }
    void pre(int l){
        for (t=1,p=0;t<l;t<<=1,p++);
        for (int i=0;i<t;i++)
            re[i]=(re[i>>1]>>1)|((i&1)<<(p-1));
    }
    void Ntt(int *a,int o){
        for (int i=0;i<t;i++)
            if (i<re[i]) swap(a[i],a[re[i]]);
        for (int wn,i=1;i<t;i<<=1){
            wn=K(G[o],(P-1)/(i<<1));
            for (int x,y,j=0;j<t;j+=(i<<1))
                for (int w=1,k=0;k<i;k++,w=1ll*w*wn%P)
                    x=a[j+k],y=1ll*w*a[i+j+k]%P,
                    a[j+k]=X(x+y),a[i+j+k]=X(x-y+P);
        }
        if (o)
            for (int i=0,v=K(t,P-2);i<t;i++)
                a[i]=1ll*a[i]*v%P;
    }
    void inv(int *a,int *b,int l){
        if (l==1){
            b[0]=K(a[0],P-2);
            return;
        }
        inv(a,b,(l+1)>>1);
        for (int i=0;i<l;i++)
            A[i]=a[i],B[i]=b[i];
        pre(l<<1);Ntt(A,0);Ntt(B,0);
        for (int i=0;i<t;i++)
            A[i]=1ll*A[i]*B[i]%P*B[i]%P;
        Ntt(A,1);
        for (int i=0;i<l;i++)
            b[i]=X(X(b[i]<<1)+P-A[i]);
        for (int i=0;i<t;i++) A[i]=B[i]=0;
    }
    void dvs(int *f,int *g,int *q,int *d){
        reverse(f,f+n+1);reverse(g,g+m+1);
        inv(g,q,n-m+1);
        for (int i=0;i<=n-m;i++)
            A[i]=q[i],B[i]=f[i];
        pre((n-m+1)<<1);Ntt(A,0);Ntt(B,0);
        for (int i=0;i<t;i++)
            A[i]=1ll*A[i]*B[i]%P;
        Ntt(A,1);
        for (int i=0;i<=n-m;i++) q[i]=A[i];
        for (int i=0;i<t;i++) A[i]=B[i]=0;
        reverse(q,q+n-m+1);
        reverse(f,f+n+1);reverse(g,g+m+1);
        for (int i=0;i<=m;i++) A[i]=g[i];
        for (int i=0;i<=n-m;i++) B[i]=q[i];
        pre(n+2);Ntt(A,0);Ntt(B,0);
        for (int i=0;i<t;i++)
            A[i]=1ll*A[i]*B[i]%P;
        Ntt(A,1);
        for (int i=0;i<m;i++)
            d[i]=X(f[i]-A[i]+P);
        for (int i=0;i<t;i++) A[i]=B[i]=0;
    }
    int main(){
        cin>>n>>m;
        for (int i=0;i<=n;i++)
            scanf("%d",&f[i]);
        for (int i=0;i<=m;i++)
            scanf("%d",&g[i]);
        dvs(f,g,q,d);
        put(q,n-m);put(d,m-1);
        return 0;
    }
  • 相关阅读:
    可怕的沉默
    我排着队 拿着号码牌
    移动改名正在运行的程序
    C# 注册热键
    c#通过编码检查是否有PendingChanges没有签入
    c#读取带命名空间的xml
    自动查找并关闭窗口
    C# 应用微软的Visual Studio International Pack 类库提取汉字拼音首字母
    C#执行DOS命令(CMD命令) (转)
    asp.net 文件下载,有进度条
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12241675.html
Copyright © 2020-2023  润新知