您的位置:首页 > 其它

POJ 1737 Connected Graph(组合)

2012-10-27 15:51 369 查看
题目链接:http://poj.org/problem?id=1737

题意:求n个点的连通图的个数。

思路:n个节点的完全图有C(n,2)条边。我们可以从中选0,1,2,……C(n,2)条,所以n个结点的总方案数为2^C(n,2)。其中有不连通的情况。设与结点1在一个块中的点为k个,除1外的另外的k-1个点从n-1个点中选取,而包含1的k个结点是个连通图,所以有C(n-1, k-1) * f(k)种方案。而剩下的n-k个结点各点之间任意连接方案数为2^C(n-k, 2),所以总的不连通的方案数为sigama(C(n-1, k-1)*f(k)*2^C(n-k,2))(1<=k<=n-1)。所以f(n) = 2^C(n,2) -sigama( C(n-1, k-1) * f(k) * 2^C(n-k,2))。(1<=k<=n-1)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const __int64 MOD=10000000;
class BigNum
{
public:
__int64 a[200];
public:
BigNum operator+(BigNum temp)
{
BigNum ans;
__int64 i,j,k,p;
if(a[0]>temp.a[0]) p=a[0];
else p=temp.a[0];
for(i=a[0],j=temp.a[0],k=p;j>=1&&i>=1;i--,j--,k--)
ans.a[k]=a[i]+temp.a[j];
if(j==0)
{
while(i>=1) ans.a[i]=a[i--];
}
else
{
while(j>=1) ans.a[j]=temp.a[j--];
}
ans.a[0]=0;
for(i=p;i>=1;i--)
{
ans.a[i-1]+=ans.a[i]/MOD;
ans.a[i]%=MOD;
}
if(ans.a[0])
{
for(i=p+1;i>=1;i--) ans.a[i]=ans.a[i-1];
ans.a[0]=p+1;
}
else ans.a[0]=p;
return ans;
}

BigNum operator-(BigNum temp)
{
BigNum ans;
int i,j;
for(i=0;i<=a[0];i++) ans.a[i]=a[i];
for(i=ans.a[0],j=temp.a[0];i>=1&&j>=1;i--,j--)
ans.a[i]-=temp.a[j];
for(i=ans.a[0];i>=1;i--) if(ans.a[i]<0)
{
ans.a[i]+=MOD;
ans.a[i-1]--;
}
for(i=1;i<=a[0];i++) if(ans.a[i]) break;
if(i>a[0])
{
ans.a[0]=1;
ans.a[1]=0;
return ans;
}
for(j=i;j<=a[0];j++) ans.a[j+1-i]=ans.a[j];
ans.a[0]=a[0]-i+1;
return ans;
}

BigNum operator*(BigNum temp)
{
BigNum ans;
int i,j,p=a[0]+temp.a[0]-1;
memset(ans.a,0,sizeof(ans.a));
for(i=a[0];i>=1;i--) for(j=temp.a[0];j>=1;j--)
ans.a[i+j-1]+=a[i]*temp.a[j];
ans.a[0]=0;
for(i=p;i>=1;i--)
{
ans.a[i-1]+=ans.a[i]/MOD;
ans.a[i]%=MOD;
}
if(ans.a[0])
{
for(i=p;i>=0;i--) ans.a[i+1]=ans.a[i];
ans.a[0]=p+1;
}
else ans.a[0]=p;
return ans;
}

BigNum operator*(int temp)
{
BigNum ans;
int i;
for(i=1;i<=a[0];i++) ans.a[i]=a[i]*temp;
ans.a[0]=0;
for(i=a[0];i>=1;i--)
{
ans.a[i-1]+=ans.a[i]/MOD;
ans.a[i]%=MOD;
}
if(ans.a[0])
{
for(i=a[0];i>=0;i--) ans.a[i+1]=ans.a[i];
ans.a[0]=a[0]+1;
}
else ans.a[0]=a[0];
if(ans.a[1]>=MOD)
{
for(i=ans.a[0];i>=0;i--) ans.a[i+1]=ans.a[i];
ans.a[0]++;
}
return ans;
}

public:
BigNum()
{
a[0]=1;
a[1]=0;
}

BigNum(int x)
{
if(x>=MOD) a[0]=2,a[1]=x/MOD,a[2]=x%MOD;
else a[0]=1,a[1]=x;
}

void print()
{
printf("%I64d",a[1]);
for(int i=2;i<=a[0];i++) printf("%07d",(int)a[i]);
}
};

BigNum C[55][55],p[1300],ans[55];
BigNum ONE=BigNum(1);
int n;

void init()
{
int i,j;
for(i=1;i<=50;i++) C[i][0]=C[i][i]=ONE;
for(i=2;i<=50;i++) for(j=1;j<i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1];
p[0]=ONE;
for(i=1;i<1300;i++) p[i]=p[i-1]*2;
ans[1]=ans[2]=ONE;
ans[3]=BigNum(4);
for(i=4;i<=50;i++)
{
ans[i]=p[(i-1)*i/2];
for(j=1;j<i;j++) ans[i]=ans[i]-ans[j]*C[i-1][j-1]*p[(i-j)*(i-j-1)/2];
}
}

int main()
{
init();
while(scanf("%d",&n),n)
{
ans
.print();
puts("");
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: