zoukankan      html  css  js  c++  java
  • bzoj 3625小朋友和二叉树 多项式求逆+多项式开根 好题

    题目大意

    给定n种权值
    给定m
    (F_i表示权值和为i的二叉树个数)
    (F_1,F_2...F_m)

    分析

    安利博客
    (F_d=F_L*F_R*C_{mid},L+mid+R=d)
    (F(x)=frac {1+sqrt{1-4C(x)}}{2C(x)}=frac 2{1-sqrt{1-4C(x)}})
    无解是因为(x=0)(F(x)=1)
    但是(limlimits_{x ightarrow 0})(1-sqrt{1-4C(x)}趋于0)
    (F)趋于INF
    同理可证(F(x)=frac {1-sqrt{1-4C(x)}}{2C(x)})是正确的

    姿势

    求逆和开根函数中
    static开一些临时数组
    写起来方便
    但注意初始化

    solution

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int M=262145;
    const LL Q=998244353;
    
    inline int rd(){
    	int x=0;bool f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    	for(;isdigit(c);c=getchar()) x=x*10+c-48;
    	return f?x:-x;
    }
    
    int n,m;
    LL g,ig,iv2;
    LL a[M],b[M];
    int rev[M];
    
    LL pwr(LL x,LL tms){
    	LL res=1;
    	for(;tms>0;tms>>=1){
    		if(tms&1) res=res*x%Q;
    		x=x*x%Q;
    	}
    	return res;
    }
    
    void NTT(LL *a,int N,int fl){
    	int i,j,k;
    	LL W,Wn,u,v;
    
    	for(i=0;i<N;i++) rev[i]=(rev[i>>1]>>1)|((i&1)?(N>>1):0);
    	for(i=0;i<N;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
    
    	for(i=2;i<=N;i<<=1){
    		if(fl==1) Wn=pwr(g,(Q-1)/i);
    		else Wn=pwr(ig,(Q-1)/i);
    		for(j=0;j<N;j+=i){
    			for(W=1,k=j;k<j+i/2;k++,W=W*Wn%Q){
    				u=a[k];
    				v=W*a[k+i/2]%Q;
    				a[k]=(u+v)%Q;
    				a[k+i/2]=((u-v)%Q+Q)%Q;
    			}
    		}
    	}
    	if(fl==-1){
    		LL iN=pwr(N,Q-2);
    		for(i=0;i<N;i++) a[i]=a[i]*iN%Q;
    	}
    	
    }
    
    void INV(LL*a,LL *b,int len){
    	static LL g[M],tp[M];
    	if(len==1) b[0]=pwr(a[0],Q-2);
    	else{
    		int i;
    		INV(a,b,len>>1);
    		int N=len<<1;	
    		for(i=0;i<(len>>1);i++) g[i]=b[i];
    		for(;i<N;i++) g[i]=b[i]=0;
    		for(i=0;i<len;i++) tp[i]=a[i];
    		for(;i<N;i++) tp[i]=0;
    		NTT(g,N,1);
    		NTT(tp,N,1);
    		for(i=0;i<N;i++) tp[i]=g[i]*g[i]%Q*tp[i]%Q;
    		NTT(tp,N,-1);
    		for(i=0;i<len;i++) b[i]=((2*b[i]%Q-tp[i])%Q+Q)%Q;
    	}
    }
    
    void SQR(LL*a,LL *b,int len){
    	static LL g[M],tp[M],inv_g[M];
    	if(len==1) b[0]=1;
    	else{
    		int i;
    		SQR(a,b,len>>1);
    		int N=len<<1;
    		for(i=0;i<(len>>1);i++) g[i]=b[i]%Q;
    		for(;i<N;i++) g[i]=b[i]=0;
    		for(i=0;i<N;i++) inv_g[i]=0;
    		INV(g,inv_g,len);
    		
    		for(i=0;i<len;i++) tp[i]=a[i];
    		for(;i<N;i++) tp[i]=0;
    		NTT(inv_g,N,1);
    		NTT(tp,N,1);
    		for(i=0;i<N;i++) tp[i]=inv_g[i]%Q*tp[i]%Q;
    		NTT(tp,N,-1);
    		for(i=0;i<len;i++) b[i]=(b[i]+tp[i])%Q*iv2%Q;
    	}
    }
    
    int main(){
    
    	int i,x;
    	n=rd(),m=rd();
    	for(i=1;i<=n;i++){
    		x=rd();
    		a[x]-=4;
    		if(a[x]<0) a[x]+=Q;
    	}
    	a[0]++;
    	for(n=2;n<=m;n<<=1);
    	g=3;
    	ig=pwr(3,Q-2);
    	iv2=pwr(2,Q-2);
    	
    	SQR(a,b,n);
    
    	b[0]++;
    	INV(b,a,n);
    
    	for(i=0;i<=m;i++) a[i]=(2LL*a[i])%Q;
    	for(i=1;i<=m;i++) printf("%d
    ",a[i]);
    	return 0;
    }
    
  • 相关阅读:
    Python----路由器远程控制
    进程和线程的区别
    tengine日志切割-配置分钟级别日志自动切割
    grep每次读取多大的文本
    bc 进制间转换
    二分法猜数字
    What is the difference between HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR
    Nginx配置两份日志记录
    Nginx启动报错误unlink() “nginx.pid” failed (2: No such file or directory)
    Mysql 数据库crash恢复
  • 原文地址:https://www.cnblogs.com/acha/p/6474761.html
Copyright © 2011-2022 走看看