题目意思就不赘述了。
这是一个计数问题,一开始考虑如何去重却没有想到可行的办法。
原因是只考虑计数连通的方案数是困难的。
设n阶图连通的方案数为f(n),不连通的方案数为g(n) = 2^(2, n) - f(n)。
不连通的图存在多于1个的连通分量,而每个连通分量是连通的,这是本题的切入点。
考虑点1所在的连通分量,设其节点数为k(< n),那么所求即等价于计数剩余(n - k)个节点连通或不连通方案数。
可以枚举从1到n - 1枚举k,如此有g(n) = sigma((k - 1, n - 1) * f(k) * 2 ^ (2, n - k))。
根据此递推方程计算即可。
考虑到数值结果非常大,用java内置大数。
http://poj.org/problem?id=1737
1 package sample_java_project; 2 3 import java.math.BigInteger; 4 import java.util.Scanner; 5 6 public class myfirstjava{ 7 public static BigInteger f[] = new BigInteger [55]; 8 public static BigInteger c[][] = new BigInteger [55][55]; 9 public static BigInteger power[] = new BigInteger [55]; 10 public static void main(String[] args){ 11 init(); 12 int n; 13 Scanner cin = new Scanner(System.in); 14 while(cin.hasNext()){ 15 n = cin.nextInt(); 16 if(n == 0) break; 17 System.out.println(F(n)); 18 } 19 } 20 21 public static void init(){ 22 power[0] = BigInteger.ONE; 23 for(int i = 1; i < 51; i++) power[i] = power[i - 1].multiply(BigInteger.valueOf(2)); 24 for(int i = 0; i < 55; i++) for(int j = 0; j < 55; j++) c[i][j] = BigInteger.valueOf(-1); 25 for(int i = 0; i < 55; i++) f[i] = BigInteger.valueOf(-1); 26 } 27 28 public static BigInteger C(int k, int num){ 29 if(c[k][num] != BigInteger.valueOf(-1)) return c[k][num]; 30 if(k > num) return BigInteger.ZERO; 31 if(k == 0 || k == num) return BigInteger.ONE; 32 return c[k][num] = C(k - 1, num - 1).add(C(k, num - 1)); 33 } 34 35 public static BigInteger power(BigInteger num){ 36 BigInteger ans = BigInteger.valueOf(1); 37 while(num != BigInteger.ZERO){ 38 ans = ans.multiply(BigInteger.valueOf(2)); 39 num = num.subtract(BigInteger.ONE); 40 } 41 return ans; 42 } 43 44 public static BigInteger F(int num){ 45 if(f[num] != BigInteger.valueOf(-1)) return f[num]; 46 BigInteger tem = BigInteger.ZERO; 47 for(int i = 1; i < num; i++) 48 tem = tem.add((F(i).multiply(power(C(2, num - i)))).multiply(C(i - 1, num - 1))); 49 return f[num] = power(C(2, num)).subtract(tem); 50 } 51 }
时间: 2024-10-08 19:34:57