今天做了传说中的男人八题的第一题...

这题是个组合问题,很容易想到逆着来,就是从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 }
View Code

 

posted on 2014-01-07 17:41  WCED  阅读(257)  评论(0编辑  收藏  举报