题意:有n个点,问把它们连起来的方案数
思路:n个点一共n * (n-1) / 2 条边,设为h[n],一共方案数2 ^ h[n],去掉不连通的情况,选取一个固定点,再选k(0 ≤ k < n-1)个点方案数C(n-1,k),和它连通方案数ans[k+1],其他n-1-k个点的条边随便连
ans[n] = 2^h[n]- sum{ C(n-1,k) * ans[k+1] * 2^h[ n-1-k ] } (0 ≤ k < n-1)
import java.util.*; import java.math.*; public class Main{ static BigInteger ans[] = new BigInteger[55]; static int h[] = new int[55]; static BigInteger C[][] = new BigInteger[55][55]; static BigInteger two[] = new BigInteger[2505]; public static void main(String[] args) { // TODO Auto-generated method stub two[0] = BigInteger.ONE; for(int i = 1; i < 2505; i++) two[i] = two[i-1].multiply(BigInteger.valueOf(2)); C[0][0] = BigInteger.ONE; for(int i = 1; i <= 50; i++) { for(int j = 0; j <= i; j++) { if(j == 0 || j == i) C[i][j] = BigInteger.ONE; else C[i][j] = C[i-1][j-1].add( C[i-1][j] ); } } h[1] = 0; for(int i = 2; i <= 50; i++) h[i] = i*(i-1)/2; ans[1] = BigInteger.ONE; for(int i = 2; i <= 50; i++) { BigInteger temp; temp = two[ h[i] ]; for(int j = 0; j <= i-2; j++) temp = temp.subtract(two[h[i-1-j]].multiply(ans[j+1]).multiply(C[i-1][j])); ans[i] = temp; } Scanner sc = new Scanner(System.in); while(sc.hasNext()) { int n = sc.nextInt(); if(n == 0) break; System.out.println(ans[n]); } } } /* a.add(b); 加法运算 a.subtract(b); 减法运算 a.multiply(b); 乘法运算 a.divide(b); 除法运算 a.mod(b); 取模运算 a.gcd(b); 最大公因数 a.max(b); 最大值(a,b) a.min(b); 最小值(a,b) a.modPow(k, mod); 返回(a^k)%mod a.pow(b); a.toString(); 返回大整数的string型 System.out.println(a); 自带换行的输出 System.out.print(a); 不自带换行的输出 Scanner sc = new Scanner(System.in); if(n.compareTo(BigInteger.ZERO)==0) break; */
第二次写Java,temp.subtract()完了后,竟然忘记赋给temp了,上次是add(),调了半天,果然还是不习惯