zoukankan      html  css  js  c++  java
  • 洛谷 P4512 [模板] 多项式除法

    题目:https://www.luogu.org/problemnew/show/P4512

    看博客:https://www.cnblogs.com/owenyu/p/6724611.html

    https://www.cnblogs.com/Mychael/p/9216906.html

    注意取模那里的 NTT 范围就是模数的次数;

    各处注意一下对系数数组取模(超出的位置赋0)。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const xn=(1<<18),g=3,mod=998244353;
    int n,m,a[xn],b[xn],d[xn],r[xn],rev[xn],c[xn],t[xn];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    ll pw(ll a,int b)
    {
      ll ret=1;
      for(;b;b>>=1,a=(a*a)%mod)if(b&1)ret=(ret*a)%mod;
      return ret;
    }
    int upt(int x){while(x>=mod)x-=mod; while(x<0)x+=mod; return x;}
    void ntt(int *a,int tp,int lim)
    {
      for(int i=0;i<lim;i++)
        if(i<rev[i])swap(a[i],a[rev[i]]);
      for(int mid=1;mid<lim;mid<<=1)
        {
          int wn=pw(g,(mod-1)/(mid<<1));
          if(tp==-1)wn=pw(wn,mod-2);
          for(int j=0,len=(mid<<1);j<lim;j+=len)
        {
          int w=1;
          for(int k=0;k<mid;k++,w=(ll)w*wn%mod)
            {
              int x=a[j+k],y=(ll)w*a[j+mid+k]%mod;
              a[j+k]=upt(x+y); a[j+mid+k]=upt(x-y);
            }
        }
        }
      if(tp==1)return; int inv=pw(lim,mod-2);
      for(int i=0;i<lim;i++)a[i]=(ll)a[i]*inv%mod;
    }
    void inv(int n,int *a,int *b)
    {
      if(n==1){b[0]=pw(a[0],mod-2); return;}
      inv((n+1)>>1,a,b);
      int lim=1,l=0;
      while(lim<=n+n)lim<<=1,l++;
      for(int i=0;i<lim;i++)rev[i]=((rev[i>>1]>>1)|((i&1)<<(l-1)));
      for(int i=0;i<n;i++)c[i]=a[i];
      for(int i=n;i<lim;i++)c[i]=0;
      ntt(c,1,lim); ntt(b,1,lim);
      for(int i=0;i<lim;i++)b[i]=((ll)2-(ll)c[i]*b[i])%mod*b[i]%mod;
      ntt(b,-1,lim);
      for(int i=n;i<lim;i++)b[i]=0;
    }
    void work()
    {
      reverse(a,a+n+1); reverse(b,b+m+1);
      int s=n-m+1; inv(s,b,t);
      int lim=1,l=0;
      while(lim<=s+s)lim<<=1,l++;//s
      for(int i=0;i<lim;i++)rev[i]=((rev[i>>1]>>1)|((i&1)<<(l-1)));
      for(int i=0;i<s;i++)c[i]=a[i];
      for(int i=s;i<lim;i++)c[i]=0;//
      ntt(c,1,lim); ntt(t,1,lim);
      for(int i=0;i<lim;i++)d[i]=(ll)c[i]*t[i]%mod;
      ntt(d,-1,lim);
      for(int i=s;i<lim;i++)d[i]=0;//%
      reverse(d,d+s);
      
      reverse(a,a+n+1); reverse(b,b+m+1);
      lim=1,l=0;
      while(lim<=n+n)lim<<=1,l++;//n
      for(int i=0;i<lim;i++)rev[i]=((rev[i>>1]>>1)|((i&1)<<(l-1)));  
      for(int i=0;i<s;i++)c[i]=d[i];
      for(int i=s;i<lim;i++)c[i]=0;
      ntt(b,1,lim); ntt(c,1,lim);
      for(int i=0;i<lim;i++)r[i]=(ll)b[i]*c[i]%mod;
      ntt(r,-1,lim);
      for(int i=0;i<m;i++)r[i]=((a[i]-r[i])%mod+mod)%mod;
      for(int i=m;i<lim;i++)r[i]=0;
    }
    int main()
    {
      n=rd(); m=rd();
      for(int i=0;i<=n;i++)a[i]=rd();
      for(int i=0;i<=m;i++)b[i]=rd();
      work();
      for(int i=0;i<=n-m;i++)printf("%d ",d[i]); puts("");
      for(int i=0;i<m;i++)printf("%d ",r[i]); puts("");
      return 0;
    }
  • 相关阅读:
    那些离不开的 Chrome 扩展插件
    Spring Boot 实战 —— 入门
    Maven 学习笔记
    Linux lvm 分区知识笔记
    Linux 双向 SSH 免密登录
    CentOS Yum 源搭建
    Ubuntu 系统学习
    iOS 测试三方 KIF 的那些事
    Swift 网络请求数据与解析
    iOS Plist 文件的 增 删 改
  • 原文地址:https://www.cnblogs.com/Zinn/p/10041306.html
Copyright © 2011-2022 走看看