今天做了传说中的男人八题的第一题...
这题是个组合问题,很容易想到逆着来,就是从n个点所有的连接方法中删去那些不能构成连通图的连法.
然后想法就是用f[i]记录i个点的连通图数目,然后递推.
具体来说,为了避免重复,选择一个固定点x,不管怎样,我们先选择x这个点,然后再从其他剩余的n-1个点中分别选0~n-2个点与x构成连通图.然后其他剩余的n-1~1个点他们之间的连接方法随意,也就是2^m种.m=完全图的边数=点数*(点数-1)/2.
初值f[1]=1
最后的公式也就是:f[n]=2^(n*(n-1)/2)-(f[1]*c[n-1][0]*2^((n-1)*(n-2)/2)+...+f[i]*c[n-1][i-1]*2^((n-i)*(n-i-1)/2+...+f[n-1]*c[n-1][n-2]*2^0)
贴上AC代码(注意n最大值会比50大,所以再往后多求几位)
1 #include <stdio.h> 2 #define maxn 65 3 typedef struct 4 { 5 int len,v[maxn]; 6 }inf; 7 typedef struct 8 { 9 int len,nu[1000]; 10 }big; 11 inf c[maxn][maxn]; 12 big nowf[65],bin[2000],res,bin2,res1; 13 bignum_add(int nowi,int nowj) 14 { 15 int jin=0,i,j,len; 16 len=c[nowi-1][nowj].len>c[nowi-1][nowj-1].len?c[nowi-1][nowj].len:c[nowi-1][nowj-1].len; 17 for(i=1;i<=len;i++) 18 { 19 c[nowi][nowj].v[i]=(c[nowi-1][nowj].v[i]+c[nowi-1][nowj-1].v[i]+jin)%10; 20 jin=(c[nowi-1][nowj].v[i]+c[nowi-1][nowj-1].v[i]+jin)/10; 21 } 22 if(jin) {c[nowi][nowj].v[i]=jin;c[nowi][nowj].len=len+1;} 23 else c[nowi][nowj].len=len; 24 } 25 bignum_times(big a,big b) 26 { 27 int i,j,jin,x,nowlen; 28 memset(res.nu,0,sizeof(res.nu)); 29 for(i=1;i<=b.len;i++) 30 for(j=1;j<=a.len;j++) 31 res.nu[i+j-1]+=a.nu[j]*b.nu[i]; 32 jin=0; 33 nowlen=a.len+b.len-1; 34 for(i=1;i<=nowlen;i++) 35 { 36 x=(res.nu[i]+jin); 37 res.nu[i]=x%10; 38 jin=x/10; 39 } 40 while(jin) 41 { 42 res.nu[++nowlen]=jin%10; 43 jin/=10; 44 } 45 res.len=nowlen; 46 } 47 bignum_bigadd(big a,big b) 48 { 49 int i,j,add1,add2,len,jin=0; 50 len=a.len>b.len?a.len:b.len; 51 for(i=1;i<=len;i++) 52 { 53 if(i>a.len) add1=0; 54 else add1=a.nu[i]; 55 if(i>b.len) add2=0; 56 else add2=b.nu[i]; 57 res.nu[i]=(add1+add2+jin)%10; 58 jin=(add1+add2+jin)/10; 59 } 60 if(jin) {res.len=len+1;res.nu[i]=jin;} 61 else res.len=len; 62 } 63 bignum_sub(big a,big b) 64 { 65 int i,subb; 66 for(i=1;i<=a.len;i++) 67 { 68 if(b.len<i) subb=0; 69 else subb=b.nu[i]; 70 if(a.nu[i]>=b.nu[i]) res.nu[i]=a.nu[i]-b.nu[i]; 71 else {res.nu[i]=a.nu[i]+10-b.nu[i];a.nu[i+1]--;} 72 } 73 while(!res.nu[a.len]) a.len--; 74 res.len=a.len; 75 } 76 main() 77 { 78 int i,j,k,n,m; 79 big nowc; 80 for(i=1;i<=60;i++) 81 for(j=0;j<=i;j++) 82 { 83 c[i][j].len=0; 84 for(k=1;k<=maxn;k++) c[i][j].v[k]=0; 85 } 86 for(i=1;i<=60;i++) {c[i][0].len=1;c[i][0].v[1]=1;} 87 c[1][1].len=1; 88 c[1][1].v[1]=1; 89 for(i=2;i<=60;i++) 90 for(j=1;j<=i;j++) 91 bignum_add(i,j); 92 bin[0].len=1; 93 bin[0].nu[1]=1; 94 bin2.len=1; 95 bin2.nu[1]=2; 96 for(i=1;i<=1771;i++) 97 { 98 bignum_times(bin[i-1],bin2); 99 bin[i].len=res.len; 100 for(j=1;j<=res.len;j++) bin[i].nu[j]=res.nu[j]; 101 } 102 nowf[1].len=1; 103 nowf[1].nu[1]=1; 104 105 for(i=2;i<=60;i++) 106 { 107 res1.len=0; 108 for(k=0;k<=i-2;k++) 109 { 110 nowc.len=c[i-1][k].len; 111 for(j=1;j<=c[i-1][k].len;j++) 112 nowc.nu[j]=c[i-1][k].v[j]; 113 bignum_times(nowc,nowf[k+1]); 114 bignum_times(res,bin[(i-1-k)*(i-2-k)/2]); 115 if(k!=0) 116 bignum_bigadd(res1,res); 117 res1.len=res.len; 118 for(j=1;j<=res.len;j++) res1.nu[j]=res.nu[j]; 119 bignum_sub(bin[i*(i-1)/2],res); 120 } 121 nowf[i].len=res.len; 122 for(j=res.len;j>=1;j--) 123 nowf[i].nu[j]=res.nu[j]; 124 } 125 while(scanf("%d",&n),n) 126 { 127 for(i=nowf[n].len;i>=1;i--) 128 printf("%d",nowf[n].nu[i]); 129 printf("\n"); 130 } 131 }