zoukankan      html  css  js  c++  java
  • HDU 5552 Bus Routes(NTT+分治)

    题意

    给定 (n) 个点,任意连边,每条边有 (m) 种颜色可选,求带环连通图的方案数。

    (1leq nleq 10000)

    (1leq m < 2^{31})

    思路

    直接求带环连通图显然比较难求,正难则反,考虑容斥。用连通图的个数减去无环连通图(树)的个数。

    (n) 个节点的无根树,每个节点有区别,可以直接套用公式 (n^{n-2}) 。而再考虑边的颜色,就是 (m^{n-1}n^{n-2})

    我们设 (n) 个点,考虑边的颜色,构成不同连通图的方案数为 (f(n))

    直接求连通图还是不方便,那么我们再容斥:用图的个数减不连通图的个数,(n) 个点,考虑边的颜色,可以有 ((m+1)^{n(n+1)over2}) 种情况,设之为 (g(n))

    有一个小 ( ext{trick}) ,我们固定一个点,选一些点和它构成一个连通块,剩下的点任意构图,显然这样是可以不重不漏的,转移式如下

    [f(n)=g(n)-sum_{i=1}^{n-1}{n-1choose i-1}f(i)g(n-i) ]

    化简得

    [f(n)=g(n)-(n-1)!sum_{i=1}^{n-1}{f(i)over (i-1)!}cdot{g(n-i)over(n-i)!} ]

    这样就是一个 (n^2)(dp) 式,并且形式上满足多项式乘法的形式,只是 (f) 在右边出现了。

    那我们只能考虑左边对右边的转移,不难想到( ext{CDQ})分治。

    void CDQ(int l,int r)
    {
    	if(l==r){/*转移常量给dp[l]*/return;}
    	int mid=(l+r)>>1;
    	CDQ(l,mid);
    	/*处理[l,mid]的多项式和转移给[mid+1,r]的多项式*/ 
    	_Polynomial::multiply(/**/);
    	/*转移结果给dp[mid+1,r]*/
    	CDQ(mid+1,r);
    	return;
    }
    

    代码流程如上,在分治过程中考虑左边转移给右边,需保证在转移前,左边的值以计算完毕。

    ( ext{dp})式一般写成 (dp_i=A_icdot sum dp_jf_{i-j}+B_i) 看的会比较清晰。

    代码

    #include<bits/stdc++.h>
    #define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
    #define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
    using namespace std;
    template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
    template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
    typedef long long ll;
    const int P=152076289;
    const int N=1<<14|5;
    namespace _Maths
    {
    	ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    	void exgcd(ll a,ll b,ll &x,ll &y)
    	{
    		if(!b){x=1,y=0;return;}
    		exgcd(b,a%b,y,x),y-=a/b*x;
    	}
    	ll Pow(ll a,ll p,ll P)
    	{
    		ll res=1;
    		for(;p>0;p>>=1,(a*=a)%=P)if(p&1)(res*=a)%=P;
    		return res;
    	}
    	ll inv(ll a,ll P){ll x,y;exgcd(a,P,x,y);return (x%P+P)%P;}
    };
    using namespace _Maths;
    namespace _Polynomial
    {
    	const int g=106;
    	int A[N<<1],B[N<<1];
    	int w[N<<1],r[N<<1];
    	void DFT(int *a,int op,int n)
    	{
    		FOR(i,0,n-1)if(i<r[i])swap(a[i],a[r[i]]);
    		for(int i=2;i<=n;i<<=1)
    			for(int j=0;j<n;j+=i)
    				for(int k=0;k<i/2;k++)
    				{
    					int u=a[j+k],t=(ll)w[op==1?n/i*k:(n-n/i*k)&(n-1)]*a[j+k+i/2]%P;
    					a[j+k]=(u+t)%P,a[j+k+i/2]=(u-t)%P;
    				}
    		if(op==-1)
    		{
    			int I=inv(n,P);
    			FOR(i,0,n-1)a[i]=(ll)a[i]*I%P;
    		}
    	}
    	void multiply(const int *a,const int *b,int *c,int n1,int n2)
    	{
    		int n=1;
    		while(n<n1+n2-1)n<<=1;
    		FOR(i,0,n1-1)A[i]=a[i];
    		FOR(i,0,n2-1)B[i]=b[i];
    		FOR(i,n1,n-1)A[i]=0;
    		FOR(i,n2,n-1)B[i]=0;
    		FOR(i,0,n-1)r[i]=(r[i>>1]>>1)|((i&1)*(n>>1));
    		w[0]=1,w[1]=Pow(g,(P-1)/n,P);
    		FOR(i,2,n-1)w[i]=(ll)w[i-1]*w[1]%P;
    		
    		DFT(A,1,n),DFT(B,1,n);
    		FOR(i,0,n-1)A[i]=(ll)A[i]*B[i]%P;
    		DFT(A,-1,n);
    		FOR(i,0,n1+n2-2)c[i]=(A[i]+P)%P;
    	}
    };
    int A[N],B[N],C[N<<1];
    int fac[N],ifac[N],f[N],g[N];
    int n;ll m;
    
    void CDQ(int l,int r)
    {
    	if(l==r){f[l]=(g[l]-(ll)fac[l-1]*f[l]%P)%P;return;}
    	int mid=(l+r)>>1;
    	CDQ(l,mid);
    	FOR(i,l,mid)A[(i)-l]=(ll)f[i]*ifac[i-1]%P;
    	FOR(i,1,r-l)B[(i)-1]=(ll)g[i]*ifac[i]%P;
    	_Polynomial::multiply(A,B,C,mid-l+1,r-l);
    	FOR(i,mid+1,r)f[i]=((ll)f[i]+C[(i)-l-1])%P;
    	CDQ(mid+1,r);
    }
    
    int main()
    {
    	fac[0]=fac[1]=1;FOR(i,2,N-1)fac[i]=(ll)fac[i-1]*i%P;
    	ifac[0]=ifac[1]=1;FOR(i,2,N-1)ifac[i]=(ll)(P-P/i)*ifac[P%i]%P;
    	FOR(i,2,N-1)ifac[i]=(ll)ifac[i-1]*ifac[i]%P;
    	int T;
    	scanf("%d",&T);
    	FOR(Ti,1,T)
    	{
    		scanf("%d%lld",&n,&m);
    		FOR(i,1,n)f[i]=0;
    		FOR(i,1,n)g[i]=Pow(m+1,(ll)i*(i-1)/2,P);
    		CDQ(1,n);
    		printf("Case #%d: %lld
    ",Ti,(((ll)f[n]-Pow(n,n-2,P)*Pow(m,n-1,P))%P+P)%P);
    	}
    	return 0;
    }
    
  • 相关阅读:
    keyCode对照表
    WebApi的前端调用
    AJAX get和post请求
    Linq中常用语法
    MVC三种分页方法
    常用DBhelper封装方法
    ASP.NET MVC 导入Excel文件(完整版)
    Razor语法2
    MVC之路由规则 (自定义,约束,debug)
    MVC
  • 原文地址:https://www.cnblogs.com/Paulliant/p/10272312.html
Copyright © 2011-2022 走看看