题目:​​poj1737 Connected Graph​​​
问题:含有n个不同的点的连通图有多少种,即同构的图算是多个

ll f[maxn];       //含n个点的连通图个数
ll g[maxn]; //含n个点的不连通图个数
ll h[maxn]; //含n个点的图的个数 h[n] = 2^(n*(n-1)/2)
ll c[maxn][maxn]; //组合数
/*
f[n] = h[n]-g[n]
要想求f[n],必须先求g[n]
求g[n]
g[n] = sum(k:1~n-1)(c[n-1][k-1]*f[k]*h[n-k])
初始值:f[1] = g[1] = 1;
c[m][n] = m!/(n!*(m-n)!)
*/
ll qpow(ll x,ll n)
{
ll res = 1;
while(n)
{
if(n&1)
res = res*x%mod;
x = x*x%mod;
n >>= 1;
}
return res;
}
void init()
{
for(ll i = 1;i<maxn;i++)
h[i] = qpow(2,i*(i-1)/2);
for(int i=0;i<maxn;i++)
{
for(int j=0;j<=i;j++)
{
if(i&&j)
c[i][j] = (c[i-1][j]+c[i-1][j-1])%mod;
else
c[i][j] = 1;
}
}
f[1] = g[1] = 1;
for(int i=2;i<maxn;i++)
{
g[i] = 0;
for(int k = 1;k<i;k++)
g[i] = (g[i]+c[i-1][k-1]*f[k]%mod*h[i-k]%mod)%mod;
f[i] = ((h[i]-g[i])%mod+mod)%mod;
}
}
import java.util.*;
import java.math.*;
public class Main {
static final int maxn = 105;
static BigInteger[] f = new BigInteger[maxn];
static BigInteger[] two = new BigInteger[maxn];
static BigInteger[] g = new BigInteger[maxn];
static BigInteger[] h = new BigInteger[maxn];
static BigInteger[][] c = new BigInteger[maxn][maxn];
static void init()
{
two[0] = BigInteger.ONE;
for(int i=1;i<maxn;i++)
two[i] = two[i-1].multiply(BigInteger.valueOf(2));
for(int i=1;i<maxn;i++)
{
int a = i;
int b = i-1;
if(a%2==0)
a/=2;
else
b/=2;
h[i] = BigInteger.ONE;
for(int j=0;j<a;j++)
h[i] = h[i].multiply(two[b]);
}
for(int i=0;i<maxn;i++)
{
for(int j=0;j<=i;j++)
{
if(i==j || j==0)
c[i][j] = BigInteger.ONE;
else
c[i][j] = c[i-1][j].add(c[i-1][j-1]);
}
}
f[1] = g[1] = BigInteger.ONE;
for(int i=2;i<maxn;i++)
{
g[i] = BigInteger.ZERO;
for(int k = 1;k<i;k++)
g[i] = g[i].add(c[i-1][k-1].multiply(f[k]).multiply(h[i-k]));
f[i] = h[i].subtract(g[i]);
}
}
public static void main(String[] args) {
init();
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
System.out.println(f[n]);
cin.close();
}
}