• 多项式全家桶


    放个板子

    #define ll long long
    #define cri const register int
    #define re register
    #define int ll
    #define cp const cplx
    using namespace std;
    #define vcp vector<cplx>
    #define vdb vector<double>
    #define vnt vector<int>
    #define cp const cplx
    #define rs(x) x.resize(bin) 
    #define P 3.141592653589793L
    const int lim=(1<<15);
    const int mod=998244353;
    inline void db(vnt &a,cri bin){
    	for(int i=0;i<bin;i++) cout<<a[i]<<" "; puts("");
    }
    inline ll qpow(ll a,ll b,ll ans=1){
    	for(;b;b>>=1,a=a*a%mod) if(b&1) ans=ans*a%mod;
    	return ans;
    }
    inline void rnt(vnt &A,cri bin){
    	rs(A);
    	for(int i=0;i<bin;i++) A[i]=0;
    }
    inline int r(double x){
    	return (int)(x+0.5);
    }
    inline int mo(cri x){
    	return x>=mod?x-mod:x;
    }
    struct cplx{
    	double rl,ig;
    	cplx(double r=0,double i=0){ this->rl=r;this->ig=i; }
    	friend cplx operator + (const cplx &a,const cplx &b){
    		return cplx(a.rl+b.rl,a.ig+b.ig);
    	}
    	friend cplx operator - (const cplx &a,const cplx &b){
    		return cplx(a.rl-b.rl,a.ig-b.ig);
    	}
    	friend cplx operator * (const cplx &a,const cplx &b){
    		return cplx(a.rl*b.rl-a.ig*b.ig,a.rl*b.ig+b.rl*a.ig);
    	}
    };
    vcp ww[19];
    inline void put(vnt &A,cri bin){
    	for(int i=0;i<bin;i++) printf("%d ",A[i]);puts("");
    }
    struct node{
    	vnt pd[250010];
    	inline void clear(vnt &A,cri len,cri bin){ for(int i=len;i<bin;i++) A[i]=0; }
    	inline void ntt(vnt &A,cri bin,cri opt){
    		vnt v;rnt(v,bin);
    		for(int i=0;i<bin;i++) v[i]=v[i>>1]>>1|(i&1?bin>>1:0);//,cout<<v[i]<<" ";puts("");
    		for(int i=0;i<bin;i++) if(i<v[i]) swap(A[i],A[v[i]]);
    		for(int i=1;i<bin;i<<=1){
    			const ll wn=qpow(3,opt*(mod-1)/(i<<1)+mod-1);
    			for(int j=0,w=1;j<bin;j+=(i<<1),w=1)
    				for(int k=0;k<i;k++,w=w*wn%mod) {
    					ll x=A[j+k],y=w*A[j+k+i]%mod;
    					A[j+k]=mo(x+y);A[j+k+i]=mo(x-y+mod);
    				}
    		}
    		if(opt==-1) for(int i=0,pw=qpow(bin,mod-2);i<bin;i++) A[i]=A[i]*pw%mod;
    	}
    	inline void fft(vcp &A,cri bin,cri opt){
    		vnt v;rnt(v,bin);
    		for(int i=0;i<bin;i++) v[i]=v[i>>1]>>1|(i&1?bin>>1:0);
    		for(int i=0;i<bin;i++) if(i<v[i]) swap(A[i],A[v[i]]);
    		for(int i=1,g=0;i<bin;i<<=1,g++)
    			for(int j=0;j<bin;j+=(i<<1))
    				for(int k=0;k<i;k++){
    					cp x=A[j+k],y=ww[g][k]*A[j+k+i];
    					A[j+k]=x+y;A[j+k+i]=x-y;
    				}
    		if(opt==1) return;
    		reverse(A.begin()+1,A.begin()+bin);
    		for(int i=0;i<bin;i++) A[i].rl/=bin;
    	}
    	inline void mul(vnt &A,vnt &B,cri bin,cri opt){
    		if(!opt){	
    			ntt(A,bin,1);ntt(B,bin,1);
    			for(int i=0;i<bin;i++) A[i]=A[i]*B[i]%mod;
    			ntt(A,bin,-1);ntt(B,bin,-1);
    		}
    		else {
    			vcp p1,p2,p3,p4;rs(p1);rs(p2);rs(p3);rs(p4);
    			for(int i=0;i<bin;i++)
    				p1[i]=cplx(A[i]>>15,0),p2[i]=cplx(A[i]&(lim-1),0),
    				p3[i]=cplx(B[i]>>15,0),p4[i]=cplx(B[i]&(lim-1),0);
    			fft(p2,bin,1);fft(p4,bin,1);fft(p3,bin,1);fft(p1,bin,1);
    			for(int i=0;i<bin;i++){
    				const cplx a=p1[i],b=p2[i],c=p3[i],d=p4[i];
    				p1[i]=a*c;p2[i]=(b*c)+(a*d);p3[i]=d*b;
    			}
    			fft(p3,bin,-1);fft(p1,bin,-1);fft(p2,bin,-1);
    			for(int i=0;i<bin;i++)
    				A[i]=(r(p1[i].rl)%mod*lim%mod*lim%mod+r(p2[i].rl)%mod*lim%mod+r(p3[i].rl))%mod;
    		}
    	}
    	void inv(vnt &A,vnt &B,cri len,cri opt){
    		if(len==1) return B[0]=qpow(A[0],mod-2),void();
    		inv(A,B,len+1>>1,opt);
    		int bin=1;
    		while(bin<len+len) bin<<=1;
    		vnt t1,t2;rnt(t1,bin);rnt(t2,bin);
    		for(int i=0;i<len;i++) t1[i]=A[i],t2[i]=B[i];
    		clear(B,len,bin);
    		mul(t1,t2,bin,opt); 
    		clear(t1,len,bin);
    		mul(t1,t2,bin,opt);
    		for(int i=0;i<len;i++) B[i]=(B[i]*2-t1[i]+mod)%mod;
    	}
    	void sqrt(vnt &A,vnt &B,cri len,cri opt){
    		if(len==1) return B[0]=1,void();
    		sqrt(A,B,len+1>>1,opt);
    		int bin=1;
    		while(bin<len+len) bin<<=1;
    		vnt t3,t4,tmp;rnt(t3,bin);rnt(t4,bin);rnt(tmp,bin);
    		for(int i=0;i<len;i++) t3[i]=A[i],t4[i]=B[i];
    		clear(B,len,bin);
    		inv(t4,tmp,len,opt);
    		mul(t3,tmp,bin,opt);
    		for(int i=0,p=qpow(2,mod-2);i<len;i++) B[i]=(t3[i]+B[i])*p%mod;
    	}
    	inline void dao(vnt &A,vnt &B,cri bin){ 
    		for(int i=1;i<bin;i++) B[i-1]=A[i]*i%mod;B[bin-1]=0; 
    	}
    	inline void jifen(vnt &A,vnt &B,cri bin){
    		for(int i=1;i<bin-1;i++) B[i]=A[i-1]*qpow(i,mod-2)%mod;B[0]=0;
    	}
    	inline void ln(vnt &A,vnt &B,cri len,cri opt,int bin=1){
    		while(bin<len+len) bin<<=1;
    		vnt t5,t6;rnt(t5,bin);rnt(t6,bin);
    		inv(A,t5,len,opt);
    		dao(A,t6,bin);
    		mul(t5,t6,bin,opt);
    		jifen(t5,B,bin);
    	}
    	void exp(vnt &A,vnt &B,cri len,cri opt,int bin=1){
    		if(len==1) return B[0]=1,void();
    		exp(A,B,len+1>>1,opt);
    		while(bin<len+len) bin<<=1;
    		vnt t7;rnt(t7,bin);
    		clear(B,len,bin);
    		ln(B,t7,len,opt);
    		for(int i=0;i<len;i++) t7[i]=mo(A[i]-t7[i]+mod);t7[0]++;
    		mul(B,t7,bin,opt);clear(B,len,bin);
    	}
    	void prod(cri k,vnt &A,cri l,cri r,cri n,cri opt,int bin=1){
    		while(bin<=n) bin<<=1;rnt(pd[k],bin<<1);
    		if(l==r) return pd[k][0]=mod-A[l],pd[k][1]=1,void();
    		cri mid=l+r>>1,L=k<<1,R=L|1;;
    		prod(L,A,l,mid,mid-l+1,opt);prod(R,A,mid+1,r,r-mid,opt);
    		ntt(pd[L],bin,1);ntt(pd[R],bin,1);
    		for(int i=0;i<bin;i++) pd[k][i]=pd[L][i]*pd[R][i]%mod;
    		ntt(pd[L],bin,-1);ntt(pd[R],bin,-1);ntt(pd[k],bin,-1);
    	}
    	void div(vnt &F,vnt &G,vnt &PP,vnt &Q,cri n,cri m,cri opt){
    		if(n<m) return Q=F,void();
    		vnt G0=G,invG;int bin=1,M=min(m+1,n-m+1);
    		while(bin<M+M) bin<<=1;
    		rnt(invG,bin);
    		for(int i=0;i<M;i++) PP[i]=F[n-i];
    		reverse(G0.begin(),G0.begin()+m+1);//put(G0,bin);
    		inv(G0,invG,M,opt);
    		mul(PP,invG,bin,opt);
    		reverse(PP.begin(),PP.begin()+M);clear(PP,M,bin);
    		Q=G;mul(Q,PP,Q.size(),opt);
    		for(int i=0;i<m;i++) Q[i]=mo(F[i]-Q[i]+mod);
    	}
    	void solve(cri k,vnt &A,vnt &ANS,cri l,cri r,cri n,cri opt){
    		if(l==r){ ANS[l]=A[0];return; }
    		int mid=l+r>>1,L=k<<1,R=L|1,bin=1;
    		while(bin<=n+n) bin<<=1;
    		vnt q1,q2;
    		
    		rnt(q1,bin);rnt(q2,bin);
    		div(A,pd[L],q1,q2,n,mid-l+1,opt);
    		solve(L,q2,ANS,l,mid,mid-l,opt);
    		
    		rnt(q1,bin);rnt(q2,bin);
    		div(A,pd[R],q1,q2,n,r-mid,opt);
    		solve(R,q2,ANS,mid+1,r,r-mid-1,opt);
    	}
    	void fst_get(vnt &A,vnt &ND,vnt &ANS,cri n,cri m,cri opt,int bin=1){
    		prod(1,ND,1,m,m,0);
    		solve(1,A,ANS,1,m,n,0);
    	}
    }ntt;
    signed main(){
    }
    
  • 相关阅读:
    Passing Reference by value
    WPF中override ResourceDictionary中的设置的方法
    WPF中TextBox的PreviewMouseLeftButtonUp事件
    Attribute的理解和认识
    IIS添加服务
    Unix时间戳转换成C#中的DateTime
    KMP算法的实现
    IDA 宏定义
    实验吧-catalyst-system
    python整数转ASCII码
  • 原文地址:https://www.cnblogs.com/mikufun-hzoi-cpp/p/12073489.html
Copyright © 2020-2023  润新知