Sea題解(計數+DP)

題意

nn個點,不超過kk條割邊的有標號圖個數。1n50,0k501\le n\le50,0\le k\le50

題解

調得懷疑人生了,總算A了。。。

nn個點的圖個數爲ene_nnn個點連通圖個數爲lnl_nnn個點強連通圖個數爲gng_nnn個點kk條割邊的連通圖個數爲fn,kf_{n,k},則答案可以由ff數組求出。

顯然有
en=2n(n1)2ln=eni=1n1(n1i1)enili e_n=2^{\frac{n(n-1)}2}\\ l_n=e_n-\sum_{i=1}^{n-1}{n-1\choose i-1}e_{n-i}l_i
gng_n需要一個輔助數組Gk,nG_{k,n},代表有kk個點,把另外nn個點劃分成一些連通塊,每個連通塊向這kk個點連邊的方案數,


Gk,n=i=1n(n1i1)li×ik×Gk,nign=lni=1n1(n1i1)giGi,ni G_{k,n}=\sum_{i=1}^n{n-1\choose i-1}l_i\times ik\times G_{k,n-i}\\ g_n=l_n-\sum_{i=1}^{n-1}{n-1\choose i-1}g_iG_{i,n-i}
fn,kf_{n,k}需要一個輔助數組Fk,j,iF_{k,j,i},代表有k+ik+i個點,可以在ii個點之間連邊或者把它們和剩下kk個點連邊,有jj條割邊的方案數,


fi,j=k=1i1(i1k1)gkFk,j,ikFk,j,i=I=0iJ=0j1(i1I1)fI,J×kI×Fk,jJi,iI f_{i,j}=\sum_{k=1}^{i-1}{i-1\choose k-1}g_kF_{k,j,i-k}\\ F_{k,j,i}=\sum_{I=0}^i\sum_{J=0}^{j-1}{i-1\choose I-1}f_{I,J}\times kI\times F_{k,j-J-i,i-I}

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define IN inline
#define R register int
const int N=55;
const ll p=1000000007;
int n,k;
ll e[N],c[N][N],l[N],g[N],G[N][N],f[N][N],F[N][N][N],ans[N][N],S;
IN ll add(ll a,ll b){return a+b<p?a+b:a+b-p;}
IN ll sub(ll a,ll b){return a-b<0?a-b+p:a-b;}
IN ll mul(ll a,ll b){return a*b%p;}
IN ll expo(ll a,int b){
	static ll c;c=1;
	while(b){
		if(b&1)c=c*a%p;
		b>>=1; a=a*a%p;
	}
	return c;
}
int main(){
	scanf("%d%d",&n,&k);
	for(R i=1;i<=n;i++)e[i]=expo(2,(i*(i-1))>>1);
	for(R i=0;i<=n;i++)c[i][0]=1;
	for(R i=1;i<=n;i++)for(R j=1;j<=i;j++)c[i][j]=add(c[i-1][j],c[i-1][j-1]);
	for(R i=1;i<=n;i++){
		l[i]=e[i];
		for(R j=1;j<i;j++)l[i]=sub(l[i],mul(mul(c[i-1][j-1],e[i-j]),l[j]));
	}
	for(R k=1;k<=n;k++)G[k][0]=1;
	for(R k=1;k<=n;k++)for(R i=1;i<=n-k;i++)for(R j=1;j<=i;j++)
		G[k][i]=add(G[k][i],mul(mul(c[i-1][j-1],j*k),mul(l[j],G[k][i-j])));
	g[0]=1;
	for(R i=1;i<=n;i++){
		g[i]=l[i];
		for(R j=1;j<i;j++)g[i]=sub(g[i],mul(mul(c[i-1][j-1],G[j][i-j]),g[j]));
	}
	for(R i=1;i<=n;i++)F[i][0][0]=1;
	for(R i=1;i<=n;i++){
		f[i][0]=g[i];
		for(R j=1;j<i;j++)for(R k=1;k<i;k++)
			f[i][j]=add(f[i][j],mul(mul(c[i-1][k-1],g[k]),F[k][j][i-k]));
		for(R k=1;k<=n-i;k++)for(R j=0;j<i+k;j++)
			for(R I=1;I<=i;I++)for(R J=0;J<j;J++)
				F[k][j][i]=add(F[k][j][i],mul(mul( c[i-1][I-1],mul(f[I][J],k*I) ),F[k][j-J-1][i-I]));
	}
	ans[0][0]=1;
	for(R i=1;i<=n;i++)for(R j=0;j<=i;j++)
		for(R I=1;I<=i;I++)for(R J=0;J<=j;J++)ans[i][j]=add(ans[i][j],mul(c[i-1][I-1],mul(f[I][J],ans[i-I][j-J])));
	for(R i=0;i<=k;i++)S=add(S,ans[n][i]);
	printf("%lld",S);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章