【BZOJ】【1005】【HNOI2008】明明的烦恼
Prufer序列/排列组合+高精度
窝不会告诉你我是先做了BZOJ1211然后才来做这题的>_>(为什么?因为我以前不会高精度呀……)
在A了BZOJ 1211和1089之后,蒟蒻终于有信心来写这道神题啦= =
嗯还是先说下做法吧~
……
还是出门左转去看黄学长的博客吧……我懒得写了……其实就是Prufer序列+高精度= =嗯就是之前说的那两道题的加和……
1 /************************************************************** 2 Problem: 1005 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:188 ms 7 Memory:1304 kb 8 ****************************************************************/ 9 10 //BZOJ 1005 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 #define pb push_back 20 using namespace std; 21 typedef long long LL; 22 inline int getint(){ 23 int r=1,v=0; char ch=getchar(); 24 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 25 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 26 return r*v; 27 } 28 const int N=1010; 29 /*******************template********************/ 30 31 32 struct bint{ 33 int l,v[5010]; 34 bint(){l=1; memset(v,0,sizeof v);} 35 int& operator [] (int x){return v[x];} 36 }ans; 37 const int Limit=1000; 38 39 void print(bint a){ 40 printf("%d",a[a.l]); 41 D(i,a.l-1,1) printf("%03d",a[i]); 42 puts(""); 43 } 44 bint operator * (bint a,int p){ 45 int tmp=0; 46 F(i,1,a.l){ 47 a[i]=a[i]*p+tmp; 48 tmp=a[i]/Limit; 49 a[i]%=Limit; 50 } 51 if (tmp) a[++a.l]=tmp; 52 return a; 53 } 54 int n,a[N],b[N],prime[N],tot,m,cnt; 55 bool vis[N]; 56 void ready(int n){ 57 F(i,2,n){ 58 if (!vis[i]) prime[++tot]=i; 59 F(j,1,tot){ 60 if (i*prime[j]>n) break; 61 vis[i*prime[j]]=1; 62 if (i%prime[j]==0) break; 63 } 64 } 65 } 66 void add(int k,int v){ 67 F(j,1,tot){ 68 int x=k; 69 while (x){ 70 b[j]+=x/prime[j]*v; 71 x/=prime[j]; 72 } 73 } 74 } 75 int main(){ 76 #ifndef ONLINE_JUDGE 77 freopen("1005.in","r",stdin); 78 freopen("1005.out","w",stdout); 79 #endif 80 ready(1000); 81 n=getint(); 82 if (n==1){ 83 a[1]=getint(); 84 if (a[1]<=0) puts("1"); 85 else puts("0"); 86 return 0; 87 } 88 F(i,1,n){ 89 a[i]=getint(); 90 if (a[i]==0 || a[i]>n-1) {puts("0"); return 0;} 91 } 92 F(i,1,n){ 93 if (a[i]>0){ 94 a[i]-=1; 95 m+=a[i]; 96 } 97 else cnt++; 98 } 99 if (m>n-2){ puts("0"); return 0;} 100 int tmp=n-2; 101 F(i,1,n){ 102 if (a[i]>0){ 103 add(tmp,1); 104 add(a[i],-1); 105 add(tmp-a[i],-1); 106 tmp-=a[i]; 107 } 108 } 109 // F(i,1,tot) printf("%d ",b[i]); puts(""); 110 ans[1]=1; 111 F(i,1,tot) F(j,1,b[i]) ans=ans*prime[i]; 112 F(j,1,tmp) ans=ans*cnt; 113 print(ans); 114 return 0; 115 }
1005: [HNOI2008]明明的烦恼
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2964 Solved: 1182
[Submit][Status][Discuss]
Description
自从明明学了树的结构,就对奇怪的树产生了兴趣...... 给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树?
Input
第一行为N(0 < N < = 1000),接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1
Output
一个整数,表示不同的满足要求的树的个数,无解输出0
Sample Input
3
1
-1
-1
1
-1
-1
Sample Output
2
HINT
两棵树分别为1-2-3;1-3-2
Source