zoukankan      html  css  js  c++  java
  • 洛谷6516

    简单的多项式题。
    挖掘bfs图的性质。
    显然,对于每条边((x,y))(设(d_x<d_y)),(d_x=d_y)(d_x+1=d_y)
    且每个点至少有一条边连向上一层。
    (c_i)表示有多少个(d=i)
    发现(sum C_{c_i}^2=v)较大,所以求出连向相邻层的边的生成函数,然后枚举同一层的边取多少个即可。
    同一层边取(x)个的方案是(C_v^x)
    连向相邻层的边的生成函数可以把每一层(i)连向(i+1)的生成函数求出,然后分治fft计算。
    由于每一层(i)必须向前面那一层连边,所以当连了(<c_i)条边,生成函数对应项是(0)
    当连了(=c_i)条边时,生成函数对应项是(c_{i-1}^{c_i})
    当连了(>c_i=t)条边,则我们有额外自由的(e=c_{i-1}*c_i-t)条边。
    方案数是(frac{e!}{(e-t)!})
    (s=sum c_i*c_i+1)
    时间复杂度(O(slog_2^2s))
    代码不知道为什么挂了。

    #include<bits/stdc++.h>
    using namespace std;
    #define mo 998244353
    #define N 500010
    #define ll unsigned long long
    #define pl vector<int>
    int qp(int x,int y){
    	int r=1;
    	for(;y;y>>=1,x=1ll*x*x%mo)
    		if(y&1)r=1ll*r*x%mo;
    	return r;
    }
    int rev[N],v,le,w[N];
    void deb(pl x){
    	for(int i=0;i<x.size();i++)
    		printf("%lld ",x[i]);
    	puts("");
    }
    void init(int n){
    	v=1;
    	le=0;
    	while(v<n)le++,v*=2;
    	for(int i=0;i<v;i++)
    		rev[i]=(rev[i>>1]>>1)|((i&1)<<(le-1));
    	int g=qp(3,(mo-1)/v);
    	w[v/2]=1;
    	for(int i=v/2+1;i<v;i++)
    		w[i]=1ull*w[i-1]*g%mo;
    	for(int i=v/2-1;~i;i--)
    		w[i]=w[i*2];
    }
    void fft(int v,pl &a,int t){
    	static unsigned long long b[N];
    	int s=le-__builtin_ctz(v);
       	for(int i=0;i<v;i++)
       		b[rev[i]>>s]=a[i];
    	int c=0;
    	w[0]=1;
        for(int i=1;i<v;i*=2,c++)
        	for(int r=i*2,j=0;j<v;j+=r)
                for(int k=0;k<i;k++){
                   	int tx=1ll*b[j+i+k]*w[k+i]%mo;
                	b[j+i+k]=b[j+k]+mo-tx;
                	b[j+k]+=tx;
                }
        for(int i=0;i<v;i++)
        	a[i]=b[i]%mo;
        if(t==0)return;
        int iv=qp(v,mo-2);
        for(int i=0;i<v;i++)
        	a[i]=1ull*a[i]*iv%mo;
        a.resize(v);
        reverse(a.begin()+1,a.end());
    }
    pl operator *(pl x,pl y){
    	int s=x.size()+y.size()-1;
    	if(x.size()<=20||y.size()<=20){
    		pl r;
    		r.resize(s);
    		for(int i=0;i<x.size();i++)
    			for(int j=0;j<y.size();j++)
    				r[i+j]=(r[i+j]+1ll*x[i]*y[j])%mo;
    		return r;
    	}
    	init(s);
    	x.resize(v);
    	y.resize(v);
    	fft(v,x,0);
    	fft(v,y,0);
    	//deb(x);
    	//deb(y);
    	for(int i=0;i<v;i++)
    		x[i]=1ll*x[i]*y[i]%mo;
    	fft(v,x,1);
    	x.resize(s);
    	return x;
    }
    void inv(int n,pl &b,pl &a){
    	if(n==1){
    		b[0]=qp(a[0],mo-2);
    		return;
    	}
    	inv((n+1)/2,b,a);
        static pl c;
    	init(n*2);
    	c.resize(v);
    	b.resize(v);
        for(int i=0;i<n;i++)
    		c[i]=a[i];
        fft(v,c,0);
        //deb(c);
    	fft(v,b,0);
    	//deb(b);
        for(int i=0;i<v;i++)
        	b[i]=1ll*(2ll-1ll*c[i]*b[i]%mo+mo)%mo*b[i]%mo;
        //deb(b);
        fft(v,b,1);  
       	b.resize(n);
       	//deb(b);
    }
    void ad(pl &x,pl y,int l){
    	x.resize(max((int)x.size(),(int)y.size()+l));
    	for(int i=0;i<y.size();i++)
    		x[i+l]=(x[i+l]+y[i])%mo;
    }
    pl operator +(pl x,pl y){
    	ad(x,y,0);
    	return x;
    }
    pl iv(pl x){
    	pl y;
    	int n=x.size();
    	y.resize(n);
    	inv(n,y,x);
    	y.resize(n);
    	return y;
    }
    pl operator -(pl x,pl y){
    	int s=max(x.size(),y.size());
    	x.resize(s);
    	y.resize(s);
    	for(int i=0;i<s;i++)
    		x[i]=(x[i]-y[i]+mo)%mo;
    	return x;
    }
    pl qd(pl x){
    	pl y;
    	int n=x.size();
    	y.resize(n-1);
    	//deb(x);
    	for(int i=0;i<n-1;i++)
    		y[i]=1ll*x[i+1]*(i+1)%mo;
    	//deb(y);
    	return y;
    }
    pl jf(pl x){
    	int n=x.size();
    	pl y;
    	y.resize(n+1);
    	for(int i=1;i<=n;i++)
    		y[i]=1ll*x[i-1]*qp(i,mo-2)%mo;
    	return y;
    }
    pl ln(pl x){
    	int n=x.size();
    	pl y=qd(x),z=iv(x);
    	y=y*z;
    	y=jf(y);
    	y.resize(n);
    	return y;
    }
    char bf[100];
    void wr(int x){
    	if(!x){
    		putchar('0');
    		putchar(' ');
    		return;
    	}
        int ct=0;
        while(x){
            bf[++ct]=x%10;
            x/=10;
        }
        for(int i=ct;i;i--)
            putchar(bf[i]+'0');
        putchar('
    ');
    }
    void gt(int n,pl &y,pl x){
    	if(n==1){
    		y.resize(1);
    		y[0]=1;
    		return;
    	}
    	gt((n+1)/2,y,x);
    	pl z=x,a;
    	z.resize(n);
    	y.resize(n);
    	a.resize(1);
    	a[0]=1;
    	y=y*(a-ln(y)+z);
    	y.resize(n);
    }
    pl ep(pl x){
    	pl y;
    	int n=x.size();
    	gt(n,y,x);
    	return y;
    }
    void put(pl a){
    	for(int i=0;i<a.size();i++)
    		printf("%lld ",a[i]);
    	puts("");
    }
    pl a[N];
    int d[N],c[N],jc[N],ij[N];
    int cc(int y,int x){
    	return 1ll*jc[y]*ij[x]%mo*ij[y-x]%mo;
    }
    pl fz(int l,int r){
    	if(l==r)
    		return a[l];
    	int md=(l+r)/2;
    	return fz(l,md)*fz(md+1,r);
    }
    pl qp(pl x,int y){
    	if(!y){
    		pl r;
    		r.resize(x.size());
    		r[0]=1;
    		return r;
    	}
    	int po=-1,l=x.size(),va;
    	for(int i=0;i<l;i++)
    		if(x[i]){
    			po=i;
    			break;
    		}
    	if(po==-1)return x;
    	va=x[po];
    	int vv=qp(va,mo-2);
    	for(int i=min(po,l-1);i<l;i++)
    		x[i-po]=1ll*x[i]*vv%mo;
    	x.resize(l-min(po,l));
    	x=ln(x);
    	y%=mo;
    	for(int i=0;i<x.size();i++)
    		x[i]=1ll*x[i]*(y%mo)%mo;
    	x=ep(x);
    	po*=y;
    	va=qp(va,y);
    	x.resize(l);
    	for(int i=l-1;i>=po;i--)
    		x[i]=1ll*x[i-po]*va%mo;
    	for(int i=min(l-1,po-1);~i;i--)
    		x[i]=0;
    	return x;
    }
    signed main(){
    	int n,m,ans=0,va=0;
    	scanf("%d%d",&n,&m);
    	jc[0]=ij[0]=1;
    	for(int i=1;i<N;i++)
    		jc[i]=1ll*jc[i-1]*i%mo;
    	ij[N-1]=qp(jc[N-1],mo-2);
    	for(int i=N-1;i;i--)
    		ij[i-1]=1ll*ij[i]*i%mo;
    	int md=0;
    	for(int i=1;i<=n;i++){
    		scanf("%d",&d[i]);
    		c[d[i]]++;
    		md=max(md,d[i]);
    	}
    	for(int i=0;i<n;i++)
    		va+=(c[i]-1)*c[i]/2;
    	pl x,tp;
    	x.resize(va+1);
    	for(int i=0;i<=va;i++)
    		x[i]=cc(va,i);
    	for(int i=1;i<=md;i++){
    		tp.resize(c[i-1]+1);
    		for(int j=0;j<=c[i-1];j++)
    			tp[j]=cc(c[i-1],j);
    		tp[0]=(tp[0]-1+mo)%mo;
    		tp.resize(c[i-1]*c[i]+1);
    		tp=qp(tp,c[i]);
    		a[i]=tp;
    	}
    	pl vv=fz(1,md);
    	vv=vv*x;
    	if(vv.size()>m)
    		printf("%d",vv[m]);
    	else
    		puts("0");
    }
    

    一种更方便的解释:
    相邻两层的生成函数是(((1+x)^{t_i}-1)^{t_{i+1}})
    ((1+x)^{t_i}-1)是因为(i+1)层必须向(i)层连出边。
    (t_{i+1})是因为第(i+1)层有(t_{i+1})个点。
    然而这样子这道题就太水了。
    考虑前面的式子:(((1+x)^{t_i}-1)^{t_{i+1}}),可以用ln,exp技巧。
    但是由于((1+x)^{t_i}-1)常数项(=0)所以不方便ln。
    发现不能用传统的方法转化。
    考虑整体带入。注意到(-(x^{t_i}-1))是付公主的背包中的式子。
    于是令(y=x+1,f(y)=-(1-y^{t_i})^{t_{i+1}})
    (ln((1-y^{t_i})^{t_{i+1}})=t_{i+1}ln(1-y^{t_i}))
    计算(ln(1-y^{t_i}))十分经典。
    接下来考虑令(x++)得到真实的答案。
    (sum _{igeq 0}(x+1)^i=sum_{igeq 0}sum_{jgeq 0}C_j^i=sum_{jgeq 0}x^jsum_{igeq 0}g_{i+j}frac{(i+j)!}{i!j!}=sum_{jgeq 0}frac{x^j}{j!}sum_{igeq 0}g_{i+j}frac{(i+j)!}{i!})
    这样子就能用减法卷积计算了。

  • 相关阅读:
    Django-模板系统、session、web框架、内置分页
    Django-中间件、csrf(跨站请求伪造)、auth认证模块
    Django-orm数据库查询语句
    Django视图函数
    Django-URL路由配置
    Django基础介绍
    JavaScript、jQuery操作页面
    JavaScript基础
    css属性设置-显示与隐藏、盒子阴影、固定定位
    css高级选择器
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/14442246.html
Copyright © 2011-2022 走看看