• 洛谷P4721 【模板】分治 FFT(分治FFT)


    传送门

    多项式求逆的解法看这里

    我们考虑用分治

    假设现在已经求出了$[l,mid]$的答案,要计算他们对$[mid+1,r]$的答案的影响

    那么对右边部分的点$f_x$的影响就是$f_x+=sum_{i=l}^{mid}f[i]g[x-i]$

    发现右边那个东西可以用卷积快速计算

    那么只要一边分治一边跑FFT统计贡献就行了

    说是分治FFT实际上代码里写的是NTT……

    而且分治FFT跑得好慢多项式求逆的速度是它的10倍啊……

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<algorithm>
     5 using namespace std;
     6 #define swap(x,y) (x^=y,y^=x,x^=y)
     7 #define mul(x,y) (1ll*x*y%P)
     8 #define add(x,y) (x+y>=P?x+y-P:x+y)
     9 #define dec(x,y) (x-y<0?x-y+P:x-y)
    10 using namespace std;
    11 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    12 char buf[1<<21],*p1=buf,*p2=buf;
    13 inline int read(){
    14     #define num ch-'0'
    15     char ch;bool flag=0;int res;
    16     while(!isdigit(ch=getc()))
    17     (ch=='-')&&(flag=true);
    18     for(res=num;isdigit(ch=getc());res=res*10+num);
    19     (flag)&&(res=-res);
    20     #undef num
    21     return res;
    22 }
    23 char sr[1<<21],z[20];int C=-1,Z;
    24 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    25 inline void print(int x){
    26     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    27     while(z[++Z]=x%10+48,x/=10);
    28     while(sr[++C]=z[Z],--Z);sr[++C]=' ';
    29 }
    30 const int N=400005,P=998244353;
    31 inline int ksm(int a,int b){
    32     int res=1;
    33     while(b){
    34         if(b&1) res=mul(res,a);
    35         a=mul(a,a),b>>=1;
    36     }
    37     return res;
    38 }
    39 int n,r[N],g[N],f[N],A[N],B[N],O[N],limit,l;
    40 inline void init(int len){
    41     limit=1,l=0;
    42     while(limit<len*2) limit<<=1,++l;
    43     for(int i=0;i<limit;++i)
    44     r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    45 }
    46 void NTT(int *A,int type){
    47     for(int i=0;i<limit;++i)
    48     if(i<r[i]) swap(A[i],A[r[i]]);
    49     for(int mid=1;mid<limit;mid<<=1){
    50         int R=mid<<1,Wn=ksm(3,(P-1)/R);O[0]=1;
    51         for(int j=1;j<mid;++j) O[j]=mul(O[j-1],Wn);
    52         for(int j=0;j<limit;j+=R){
    53             for(int k=0;k<mid;++k){
    54                 int x=A[j+k],y=mul(O[k],A[j+k+mid]);
    55                 A[j+k]=add(x,y),A[j+k+mid]=dec(x,y);
    56             }
    57         }
    58     }
    59     if(type==-1){
    60         reverse(A+1,A+limit);
    61         for(int i=0,inv=ksm(limit,P-2);i<limit;++i)
    62         A[i]=mul(A[i],inv);
    63     }
    64 }
    65 void CDQ(int *a,int *b,int l,int r){
    66     if(l==r) return;
    67     int mid=(l+r)>>1;CDQ(a,b,l,mid);
    68     init(r-l+1);
    69     for(int i=0;i<limit;++i) A[i]=B[i]=0;
    70     for(int i=l;i<=mid;++i) A[i-l]=a[i];
    71     for(int i=0;i<=r-l;++i) B[i]=b[i];
    72     NTT(A,1),NTT(B,1);
    73     for(int i=0;i<limit;++i) A[i]=mul(A[i],B[i]);
    74     NTT(A,-1);
    75     for(int i=mid+1;i<=r;++i) a[i]=add(a[i],A[i-l]);
    76     CDQ(a,b,mid+1,r);
    77 }
    78 int main(){
    79 //    freopen("testdata.in","r",stdin);
    80     n=read();
    81     for(int i=1;i<n;++i) g[i]=read();f[0]=1;
    82     CDQ(f,g,0,n-1);
    83     for(int i=0;i<n;++i) print(f[i]);
    84     Ot();
    85     return 0;
    86 }
  • 相关阅读:
    Remove menucool tooltip trial version
    笔记:Linux(AWS Redhat)开机启动workman进程(/etc/rc.local必须是755权限)
    workman项目设置开机自启动
    Linux应用之crontab定时任务的设置
    在aws ec2上使用root用户登录
    date_default_timezone_set()问题解决方案(PHP5.3以上的)
    Potatso Lite:[限免]ios 自由上网利器
    5+ App开发入门指南
    Nginx或Apache通过反向代理配置wss服务
    phpstudy安装redis
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9749557.html
Copyright © 2020-2023  润新知