• 分治FFT


    一、处理的问题

    给出多项式(g[0...n]),求出(f[0...n])满足(f_i=sumlimits_{j=1}^if_{i-j}g_j),边界(f_0=1)

    我们发现这是个卷积的形式,但是不能直接(FFT),因为我们并不知道(f_{i-j}),于是考虑分治。

    按照CDQ分治的方法,对于当前处理的区间([l,r]),我们先处理([l,mid]),之后考虑([l,mid])([mid+1,r])的贡献,写出来就是:(f_i+=sumlimits_{j=l}^{mid}f_j*g_{i-j})

    模板题

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    const int mod=998244353;
    const int G=3;
    const int invG=332748118;
    int n,lim,len;
    int f[maxn],g[maxn],tmp1[maxn],tmp2[maxn],pos[maxn];
    inline int read()
    {
    	char c=getchar();int res=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    	return res*f; 
    }
    inline int power(int x,int k)
    {
    	int res=1;
    	while(k)
    	{
    		if(k&1)res=1ll*res*x%mod;
    		x=1ll*x*x%mod;k>>=1;
    	}
    	return res;
    }
    inline void NTT(int* a,int op)
    {
    	for(int i=0;i<lim;i++)if(i<pos[i])swap(a[i],a[pos[i]]);
    	for(int l=1;l<lim;l<<=1)
    	{
    		int wn=power(op==1?G:invG,(mod-1)/(l<<1));
    		for(int i=0;i<lim;i+=l<<1)
    		{
    			int w=1;
    			for(int j=0;j<l;j++,w=1ll*w*wn%mod)
    			{
    				int x=a[i+j],y=1ll*w*a[i+l+j]%mod;
    				a[i+j]=(x+y)%mod;a[i+l+j]=(x-y+mod)%mod;
    			}
    		}
    	}
    	if(op==1)return;
    	int inv=power(lim,mod-2);
    	for(int i=0;i<lim;i++)a[i]=1ll*a[i]*inv%mod;
    }
    void solve(int l,int r)
    {
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	solve(l,mid);
    	for(int i=l;i<=mid;i++)tmp1[i-l]=f[i],tmp2[i-l]=g[i-l];
    	for(int i=mid+1;i<=r;i++)tmp1[i-l]=0,tmp2[i-l]=g[i-l];
    	lim=1,len=0;
    	while(lim<=r-l)lim<<=1,len++;
    	for(int i=0;i<lim;i++)pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
    	for(int i=r-l+1;i<lim;i++)tmp1[i]=tmp2[i]=0;
    	NTT(tmp1,1);NTT(tmp2,1);
    	for(int i=0;i<lim;i++)tmp1[i]=1ll*tmp1[i]*tmp2[i]%mod;
    	NTT(tmp1,-1);
    	for(int i=mid+1;i<=r;i++)f[i]=(f[i]+tmp1[i-l])%mod;
    	solve(mid+1,r);
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<n;i++)g[i]=read();
    	f[0]=1;
    	int l=1;
    	while(l<=n)l<<=1;
    	solve(0,l);
    	for(int i=0;i<n;i++)printf("%d ",f[i]);
    	return 0;
    }
    
  • 相关阅读:
    Undo/Redo的C#实现方式
    c#中@符号作用
    面向对象理解随笔
    C# 面向对象定义常量,属性,方法
    c# 字段和属性
    面向对象思想
    用C表达面向对象语言的机制——C#版
    判断生日
    查找字符
    被7整除
  • 原文地址:https://www.cnblogs.com/nofind/p/12129300.html
Copyright © 2020-2023  润新知