每个程序员都会编程序,区别在于效率.各位可以试试一下这几道题,相信大家都能做,但是能用32M以内内存在1秒内解决吗?这就是传说中楼教主的男人八题,折腾了一个月,中间也是断断续续,今天终于做完了,教主果然名不虚传啊,再次膜拜教主.有兴趣的同学可以到POJ上提交自己的程序.
第一题
题意:n个各不相同的点能组成多少无向连通图?
解:首先要搞清楚,这题必然要用高精度,因为随着n的增长无向连通图的数目的增长将比卡特兰数列更加猛烈.我用的方法是先统计出总共能组成多少无向图,再减去其中不联通的个数.设i个点能组成的无向连通图个数为a[i].n个点之间共有C(n,2)条边可连,总图个数为2^C(n,2).假设图不连通,那么节点1必定在某个连通分量中,由于图不连通,所以节点1所在连通分量节点个数可能为i=1~n-1,则剩下的k=n-i个点可以任意连接,所以a[n]=Σ(i=1->n-1){a[i]*2^C(k,2)}.想清楚之后关键问题就在于高精度了,借鉴了别人的代码之后,我又花了一下午的时间自己写了一个完全高精度模板,又在VIJOS上刷了十几道高精度题测试,然后再来写这道题,神奇的1A.
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #ifndef BIGNUM #define BIGNUM class BigNum { #define MAXSIZEOFBIGNUM 500 #define BASE 10 #define DLEN 1 public: int Len; int d[MAXSIZEOFBIGNUM]; public: BigNum(void); BigNum(const int); BigNum(const char *); BigNum(const BigNum &); BigNum & operator = (const BigNum &); void clear(void); friend istream& operator>>(istream&,BigNum&); friend ostream& operator<<(ostream&,BigNum&); bool operator == (const BigNum &) const; bool operator > (const BigNum &) const; bool operator < (const BigNum &) const; bool operator >= (const BigNum &) const; bool operator <= (const BigNum &) const; BigNum operator + (const BigNum &) const; BigNum operator - (const BigNum &) const; BigNum operator * (const BigNum &) const; BigNum operator / (const BigNum &) const; BigNum operator % (const BigNum &) const; void operator ++ (void); void operator -- (void); BigNum operator + (const int &) const; BigNum operator - (const int &) const; BigNum operator * (const int &) const; BigNum operator / (const int &) const; int operator % (const int &) const; BigNum operator ^ (const int &) const; ~BigNum () {} }; BigNum::BigNum(){ Len=0; memset(d,0,sizeof(d)); } BigNum::BigNum(const int ops){ int x=ops; Len=0; memset(d,0,sizeof(d)); while (x) { Len++; d[Len]=x%BASE; x/=BASE; } } BigNum::BigNum(const char * ops){ int L=strlen(ops)-1,b=0; memset(d,0,sizeof(d)); while (ops[b]=='0') b++; Len=0; while (L-b+1>=DLEN) { int x=0; for (int i=L-DLEN+1;i<=L;i++) x=x*10+ops[i]-'0'; Len++; d[Len]=x; L-=DLEN; } int x=0; for (int i=b;i<=L;i++) x=x*10+ops[i]-'0'; Len++; d[Len]=x; } BigNum::BigNum(const BigNum &ops):Len(ops.Len){ memset(d,0,sizeof(d)); for(int i=1;i<=Len;i++) d[i]=ops.d[i]; } BigNum & BigNum::operator = (const BigNum &ops){ memset(d,0,sizeof(d)); Len=ops.Len; for(int i=1;i<=Len;i++) d[i]=ops.d[i]; return *this; } void BigNum::clear(void){ for (int i=1;i<=MAXSIZEOFBIGNUM-2;i++) { if (d[i]<0) { d[i]+=BASE; d[i+1]--; } if (d[i]>=BASE) { d[i]-=BASE; d[i+1]++; } } for (int i=MAXSIZEOFBIGNUM-1;i>=1;i--) if (d[i]>0) { Len=i; return; } Len=0; } istream& operator>>(istream &in,BigNum &ops){ char str[MAXSIZEOFBIGNUM+100]; in>>str; int L=strlen(str),b=0; while (str[b]=='0') b++; ops.Len=0; for (int i=L-1;i>=b;i--) { ops.Len++; ops.d[ops.Len]=str[i]-'0'; } return in; } ostream& operator<<(ostream& out,BigNum& ops){ for (int i=ops.Len;i>=1;i--) out<<ops.d[i]; if (ops.Len==0) out<<"0"; return out; } bool BigNum::operator == (const BigNum &ops) const{ if (Len!=ops.Len) return false; for (int i=Len;i>=1;i--) if (d[i]!=ops.d[i]) return false; return true; } bool BigNum::operator > (const BigNum &ops) const{ if (Len<ops.Len) return false; else if (Len>ops.Len) return true; else { for (int i=Len;i>=1;i--) if (d[i]<ops.d[i]) return false; else if (d[i]>ops.d[i]) return true; } return false; } bool BigNum::operator < (const BigNum &ops) const{ if (Len<ops.Len) return true; else if (Len>ops.Len) return false; else { for (int i=Len;i>=1;i--) if (d[i]<ops.d[i]) return true; else if (d[i]>ops.d[i]) return false; } return false; } bool BigNum::operator >= (const BigNum &ops) const{ if (Len<ops.Len) return false; else if (Len>ops.Len) return true; else { for (int i=Len;i>=1;i--) if (d[i]<ops.d[i]) return false; else if (d[i]>ops.d[i]) return true; } return true; } bool BigNum::operator <= (const BigNum &ops) const{ if (Len<ops.Len) return true; else if (Len>ops.Len) return false; else { for (int i=Len;i>=1;i--) if (d[i]<ops.d[i]) return true; else if (d[i]>ops.d[i]) return false; } return true; } BigNum BigNum::operator + (const BigNum &ops) const{ BigNum ret(*this); for (int i=1;i<=ops.Len;i++) ret.d[i]+=ops.d[i]; ret.clear(); return ret; } BigNum BigNum::operator - (const BigNum &ops) const{ BigNum ret(*this); for (int i=ops.Len;i>=1;i--) ret.d[i]-=ops.d[i]; ret.clear(); return ret; } BigNum BigNum::operator * (const BigNum &ops) const{ BigNum ret,now(*this); for (int i=1;i<=now.Len;i++) for (int j=1;j<=ops.Len;j++) ret.d[i+j-1]+=now.d[i]*ops.d[j]; for (int i=1;i<=MAXSIZEOFBIGNUM-2;i++) if (ret.d[i]>=BASE) { ret.d[i+1]+=ret.d[i]/BASE; ret.d[i]%=BASE; } for (int i=MAXSIZEOFBIGNUM-1;i>=1;i--) if (ret.d[i]>0) { ret.Len=i; break; } return ret; } BigNum BigNum::operator / (const BigNum &ops) const{ BigNum now=(*this),div,mod; div.Len=now.Len; mod.Len=0; for (int j=now.Len;j>=1;j--) { mod.Len++; for (int p=mod.Len;p>=2;p--) mod.d[p]=mod.d[p-1]; mod.d[1]=now.d[j]; while (mod>=ops) { div.d[j]++; mod=mod-ops; } if (mod.Len==1 && mod.d[1]==0) mod.Len--; } div.clear(); mod.clear(); return div; } BigNum BigNum::operator % (const BigNum &ops) const{ BigNum now=(*this),div,mod; div.Len=now.Len; mod.Len=0; for (int j=now.Len;j>=1;j--) { mod.Len++; for (int p=mod.Len;p>=2;p--) mod.d[p]=mod.d[p-1]; mod.d[1]=now.d[j]; while (mod>=ops) { div.d[j]++; mod=mod-ops; } if (mod.Len==1 && mod.d[1]==0) mod.Len--; } div.clear(); mod.clear(); return mod; } void BigNum::operator ++ (void){ d[1]++; for (int i=1;i<=MAXSIZEOFBIGNUM-2;i++) if (d[i]>=BASE) { d[i]-=BASE; d[i+1]++; } else break; if (d[Len+1]>0) Len++; } void BigNum::operator -- (void){ d[1]--; for (int i=1;i<=MAXSIZEOFBIGNUM-2;i++) if (d[i]<0) { d[i]+=BASE; d[i+1]--; } else break; if (d[Len]==0) Len--; } BigNum BigNum::operator + (const int & ops) const{ BigNum ret=(*this); ret.d[1]+=ops; ret.clear(); return ret; } BigNum BigNum::operator - (const int & ops) const{ BigNum ret=(*this); ret.d[1]-=ops; ret.clear(); return ret; } BigNum BigNum::operator * (const int & ops) const{ BigNum ret(*this); for (int i=1;i<=ret.Len;i++) ret.d[i]*=ops; for (int i=1;i<=MAXSIZEOFBIGNUM-2;i++) if (ret.d[i]>=BASE) { ret.d[i+1]+=ret.d[i]/BASE; ret.d[i]%=BASE; } for (int i=MAXSIZEOFBIGNUM-1;i>=1;i--) if (ret.d[i]>0) { ret.Len=i; return ret; } ret.Len=0; return ret; } BigNum BigNum::operator / (const int & ops) const{ BigNum ret; int down=0; for(int i=Len;i>=1;i--) { ret.d[i]=(d[i]+down*BASE)/ops; down=d[i]+down*BASE-ret.d[i]*ops; } ret.Len=Len; while(ret.d[ret.Len]==0 && ret.Len>1) ret.Len--; return ret; } int BigNum::operator % (const int &ops) const{ int mod=0; for(int i=Len;i>=1;i--) mod=((mod*BASE)%ops+d[i])%ops; return mod; } BigNum BigNum::operator ^ (const int &ops) const{ BigNum t,ret(1); if(ops==0)return ret; if(ops==1)return *this; int m=ops,i; while(m>1) { t=*this; for(i=1;(i<<1)<=m;i<<=1) t=t*t; m-=i; ret=ret*t; if(m==1)ret=ret*(*this); } return ret; } #endif BigNum C(int N,int K) { BigNum ret(1); for (int i=0;i<K;i++) ret=ret*(N-i); for (int i=1;i<=K;i++) ret=ret/i; return ret; } BigNum f[60]; int main() { f[1]=1; f[2]=1; f[3]=4; f[4]=38; for (int i=5;i<=50;i++) { int pow=i*(i-1)/2; BigNum T=(BigNum)2^pow; for (int j=1;j<i;j++) { BigNum tmp,com; tmp=(BigNum)2^((i-j)*(i-j-1)/2); tmp=tmp*f[j]; com=C(i-1,j-1); tmp=tmp*com; T=T-tmp; } f[i]=T; } int N; while (scanf("%d",&N)!=EOF,N!=0) cout<<f[N]<<endl; return 0; }