[poj 1737] Connected Graph {高精度+動態規劃}

題目

http://poj.org/problem?id=1737


解題思路

F[i]F[i]表示ii個節點的無向連通圖個數,狀態轉移方程爲:
F[i]=2i(i1)/2j=1i1F[j]Ci1j12(ij)(ij1)/2\large F[i]=2^{i*(i-1)/2}-\sum_{j=1}^{i-1}F[j]*C_{i-1}^{j-1}*2^{(i-j)*(i-j-1)/2}


代碼1(沒有高精度)

#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long 
using namespace std; 
int a[55],cnt,n; ll f[55],jc[55]; 
ll ksm(ll x,ll y){
	int ans=1; 
	for(;y;x*=x,y>>=1) if (y&1) ans*=x;
	return ans; 
}
ll C(int x,int y){return jc[x]/jc[y]/jc[x-y];}
int main(){
	while (scanf("%d",&a[++cnt])&&a[cnt]!=0) n=(n<a[cnt])?a[cnt]:n; 
	jc[0]=1; f[1]=1; 
	for(register int i=1;i<=n;i++) jc[i]=jc[i-1]*i; 
	for(int i=1;i<=n;i++){
		int ans=0; 
		for(int j=1;j<=i-1;j++) 
		 	ans+=f[j]*C(i-1,j-1)*ksm((ll)2,(ll)((i-j)*(i-j-1)/2)); 
		f[i]=ksm((ll)2,(ll)(i*(i-1)/2))-ans; 
	}
	for(register int i=1;i<=cnt;i++) 
	 printf("%lld\n",f[a[i]]); 
	return 0; 
}

代碼2(xjq的高精度)

#include <cstdio>
#include <vector>
#define mod 10000
typedef unsigned long long ull;
std::vector<ull>tri[50]; std::vector<ull>c[50]; std::vector<ull>f[50];
void print(ull ans){if (ans>9) print(ans/10); putchar(ans%10+48);}
int min(int a,int b){return (a<b)?a:b;}
int main(){
	for (register int i=0;i<50;i++) c[i].push_back(1);
	for (register int i=0;i<50;i++)
		for (register int j=1;j<=i+1>>1;j++) 
		    c[i].push_back(c[i][j-1]*(i-j+2)/j);
    tri[0].push_back(1);
	for (register int i=1;i<50;i++){
		tri[i]=tri[i-1]; ull g=0,s;
        for (register int j=0;j<tri[i].size();j++){
            s=tri[i][j]*(1ll<<i)+g;
            g=s/mod; tri[i][j]=s%mod;
            }
        while (g) tri[i].push_back(g%mod),g/=mod;
	}
	f[0].push_back(1);
	for (register int i=1;i<50;i++){
		f[i]=tri[i];
		for (register int j=0;j<i;j++){
			std::vector<ull>t,t1;  t=tri[i-j-1]; t1.clear(); ull g=0,s;
            for (register int p=0;p<t.size();p++){
                s=t[p]*c[i-1][min(j,i-j)]+g;
                g=s/mod; t[p]=s%mod;
            }
            while (g) t.push_back(g%mod),g/=mod;
            for (register int p1=0;p1<t.size();p1++)
            for (register int p2=0;p2<f[j].size();p2++){
            	if (t1.size()==p1+p2) t1.push_back(t[p1]*f[j][p2]); else t1[p1+p2]+=t[p1]*f[j][p2];
            	if (t1.size()==p1+p2+1) t1.push_back(t1[p1+p2]/mod); else t1[p1+p2+1]+=t1[p1+p2]/mod;
            	t1[p1+p2]%=mod;
			}
			g=0;
			while (t1.size()<f[i].size()) t1.push_back(0);
			for (register int p=0;p<f[i].size();p++)
			if (f[i][p]>=t1[p]+g) f[i][p]-=t1[p]+g,g=0;
			    else f[i][p]+=mod-t1[p]-g,g=1;
		}
	}
	int n;
	while (scanf("%d",&n)==1&&n)
	{
		for (register int j=f[n-1].size()-1;j>=0;j--){
			ull k=mod/10; if (j<f[n-1].size()-1)
			while (k>f[n-1][j]&&k>1) putchar('0'),k/=10;
			print(f[n-1][j]);
		}
		putchar('\n');
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章