zoukankan      html  css  js  c++  java
  • 【BZOJ3456】—城市规划(生成函数+多项式求逆)

    传送门


    考虑fif_i表示ii个点连通图个数,gig_i表示ii个点的图的个数
    gi=2(i2)g_i=2^{ichoose 2}

    gng_n可以通过枚举1号点所在连通块大小表示

    gn=i=1nfigni(n1i1)g_n=sum_{i=1}^{n}f_i*g_{n-i}*{n-1choose i-1}
    gn(n1)!=i=1nfi1(i1)!gni1(ni)!frac{g_n}{(n-1)!}=sum_{i=1}^{n}f_i*frac{1}{(i-1)!}*g_{n-i}*frac{1}{(n-i)!}

    A(x)=i=1ngi(i1)!xiA(x)=sum_{i=1}^{n}frac{g_i}{(i-1)!}x^{i}

    B(x)=i=1nfi(i1)!xiB(x)=sum_{i=1}^{n}frac{f_i}{(i-1)!}x^i

    C(x)=i=0ngii!xiC(x)=sum_{i=0}^nfrac{g_i}{i!}x^i

    A(x)=B(x)C(x)A(x)=B(x)C(x)
    B(x)=A(x)C(x)B(x)=frac{A(x)}{C(x)}

    fn(n1)!=B(x)[xi]frac{f_n}{(n-1)!}=B(x)[x^i]

    多项式求逆就完了

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    const int mod=1004535809,g=3;
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    inline void Add(int &a,int b){a=add(a,b);}
    inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
    inline void Dec(int &a,int b){a=dec(a,b);}
    inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
    inline void Mul(int &a,int b){a=mul(a,b);}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
    const int N=130005;
    int rev[N<<2];
    #define poly vector<int> 
    inline void ntt(poly &f,int lim,int kd){
    	for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
    	for(int mid=1;mid<lim;mid<<=1){
    		int now=ksm(g,(mod-1)/(mid<<1));
    		for(int i=0;i<lim;i+=mid*2){
    			int w=1;
    			for(int j=0;j<mid;j++,Mul(w,now)){
    				int a0=f[i+j],a1=mul(f[i+j+mid],w);
    				f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
    			}
    		}
    	}
    	if(kd==-1&&(reverse(f.begin()+1,f.begin()+lim),1))
    		for(int i=0,inv=ksm(lim,mod-2);i<lim;i++)Mul(f[i],inv);
    }
    inline void init(int lim){
    	for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
    }
    inline poly mul(poly a,poly b){
    	int deg=a.size()+b.size()-1,lim=1;
    	if(deg<=128){
    		poly c(deg,0);
    		for(int i=0;i<a.size();i++)
    		for(int j=0;j<b.size();j++)
    			Add(c[i+j],mul(a[i],b[j]));
    		return c;
    	}
    	while(lim<deg)lim<<=1;init(lim);
    	a.resize(lim),b.resize(lim);
    	ntt(a,lim,1),ntt(b,lim,1);
    	for(int i=0;i<lim;i++)Mul(a[i],b[i]);
    	ntt(a,lim,-1),a.resize(deg);
    	return a;
    }
    inline poly Inv(poly b,int deg){
    	poly a(1,ksm(b[0],mod-2)),c;
    	for(int lim=4;lim<(deg<<2);lim<<=1){
    		init(lim),c=b,a.resize(lim);
    		c.resize(lim>>1),c.resize(lim);
    		ntt(a,lim,1),ntt(c,lim,1);
    		for(int i=0;i<lim;i++)a[i]=mul(a[i],dec(2,mul(a[i],c[i])));
    		ntt(a,lim,-1),a.resize(lim>>1);
    	}a.resize(deg);return a;
    }
    poly f,G,p;
    int fac[N],ifac[N],n;
    inline int C(int x){
    	return (1ll*x*(x-1)/2)%(mod-1);
    }
    int main(){
    	n=read(),ifac[0]=fac[0]=1;
    	for(int i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
    	ifac[n]=ksm(fac[n],mod-2);
    	for(int i=n-1;i;i--)ifac[i]=mul(ifac[i+1],i+1);
    	G.resize(n+1),p.resize(n+1);
    	for(int i=0;i<=n;i++)G[i]=mul(ifac[i],ksm(2,C(i)));
    	for(int i=1;i<=n;i++)p[i]=mul(ifac[i-1],ksm(2,C(i)));
    	G=Inv(G,n+1);
    	f=mul(p,G);
    	cout<<mul(fac[n-1],f[n]);
    }
    
  • 相关阅读:
    vue开发chrome扩展,数据通过storage对象获取
    Vue手动集成less预编译器
    Google Translate寻找之旅
    Javascript Range对象的学习
    Javascript Promises学习
    SublimeText 建立构建Node js系统
    We're sorry but demo3 doesn't work properly without JavaScript enabled. Please enable it to continue.
    npm安装包出现UNMET DEPENDENCY报错
    (转载)命令行说明中格式 尖括号 中括号的含义
    Linux重启网卡服务Failed to start LSB: Bring up/down networking.
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328817.html
Copyright © 2011-2022 走看看