orzzrt....
题意:给n个点n条边,问能形成几个无向连通图
公式:ans=Σ(k=3~n){[n^(n-k)]* (n-1)!/2(n-k)!}
推导:ans=Σ(k=3~n)(f(n,k)*h(k))
f(n,k)表示能形成的森林个数,h(k)表示能形成的环的个数
h(k)=n!/2n n!:排列的种类 n!/n:去重(123,231,312) (n!/n)/2:去重(123,321)
∴h(k)=(k-1)!/2
设g(n,k)=f(n,k)*(n-k)! (边有编号时森林的个数)
=n(n-1)n(n-2)*...*n*k
=n^(n-k)*(n-1)!/(k-1)!
∴f(n,k)=n^(n-k)*(n-1)!/[(k-1)!*(n-k)!]
∴ans=Σ(k=3~n){[n^(n-k)]* (n-1)!/2(n-k)!}
需要用到高精度
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<string> #define MAX 10010 using namespace std; char ans[MAX],sum[MAX]; int bigchenfa(int *sum2,int *a,int *b,int lsum,int la,int lb) { int i,j,k ; memset(sum2,0,sizeof(sum2)); lsum=0; for(i=1;i<=la;i++) for(j=1,lsum=i-1;j<=lb;j++) sum2[++lsum]+=b[j]*a[i]; for(i=1;i<=lsum;i++) if(sum2[i]>=10) { if(sum2[lsum]>=10) lsum++; sum2[i+1]+=sum2[i] / 10 ; sum2[i]%=10 ; } return lsum ; } void multiply(int ac) { int a[MAX]={0},b[MAX]={0},sum2[MAX*2]={0} ; int la=0,lb=1,lsum=0; int i,j; int b1=ac; la=strlen(ans); for(int i=1,j=la-1;i<=la;i++,j--) a[i]=ans[j]-'0'; while(b1>0) { b[lb]=b1%10; lb++; b1/=10; } lb-=1; lsum = bigchenfa(sum2,a,b,lsum,la,lb) ; memset(ans,0,sizeof(ans)); for(i=lsum,j=0;i>=1;i--,j++) ans[j]=sum2[i]+'0'; } int sum1[MAX],ans1[MAX]; void add() { int lena,lenb,len; lena=strlen(sum); lenb=strlen(ans); len=max(lena,lenb); memset(sum1,0,sizeof(sum1)); memset(ans1,0,sizeof(ans1)); for(int i=lena-1,j=0;i>=0;i--,j++)sum1[j]=sum[i]-'0'; for(int i=lenb-1,j=0;i>=0;i--,j++)ans1[j]=ans[i]-'0'; for(int i=0;i<len;i++) { if(sum1[i]+ans1[i]>=10) sum1[i+1]++; sum1[i]=(sum1[i]+ans1[i])%10; } if(sum1[len]!=0)len++; memset(sum,0,sizeof(sum)); for(int i=len-1,j=0;i>=0;i--,j++) { sum[j]=sum1[i]+'0'; } } void divide() { int a[MAX]={0},c[MAX]={0}; int i,k,d=0; k=strlen(sum); for(i=0;i<k;i++) a[i]=sum[k-i-1] - '0'; for(i=k-1;i>=0;i--) { d=d*10+a[i]; c[i]=d/2; d=d%2; } while(c[k-1]==0&&k>1) k--; for(i=k-1;i>=0;i--) cout<<c[i]; } int main() { int n; cin>>n; for(int k=3;k<=n;k++) { memset(ans,0,sizeof(ans)); ans[0]='1'; for(int i=1;i<=n-k;i++) { multiply(n); } for(int i=n-k+1;i<=n-1;i++) { multiply(i); } add(); } divide(); return 0; }