[BZOJ1005][HNOI2008]明明的烦恼 数学+prufer序列+高精度
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int N; 6 int A[1010],D[1010],cnt=0; 7 int sum=0,q=0; 8 int pri[1010]; 9 int ans[100010],len; 10 int main(){ 11 scanf("%d",&N); 12 if(N==1){ 13 int tmp; 14 scanf("%d",&tmp); 15 if(!tmp||tmp==-1) puts("1"); 16 else puts("0"); 17 return 0; 18 } 19 for(int i=1;i<=N;i++){ 20 scanf("%d",&A[i]); 21 if(!A[i]){ 22 puts("0"); 23 return 0; 24 } 25 if(A[i]!=-1){ 26 D[++cnt]=A[i]-1; 27 sum+=D[cnt]; 28 } 29 else q++; 30 } 31 if(N<sum+2){ 32 puts("0"); 33 return 0; 34 } 35 for(int i=1;i<=cnt;i++) 36 for(int j=2;j<=D[i];j++){ 37 int tmp=j; 38 for(int k=2;k<=j&&tmp!=1;k++) 39 while(tmp%k==0){ 40 pri[k]--; 41 tmp/=k; 42 } 43 } 44 for(int i=N-2-sum+1;i+2<=N;i++){ 45 int tmp=i; 46 for(int j=2;j<=i&&tmp!=1;j++) 47 while(tmp%j==0){ 48 pri[j]++; 49 tmp/=j; 50 } 51 } 52 ans[1]=1; 53 len=1; 54 for(int i=1;i<=N;i++){ 55 while(pri[i]){ 56 for(int j=1;j<=len;j++) ans[j]*=i; 57 for(int j=1;j<=len;j++){ 58 ans[j+1]+=ans[j]/10; 59 ans[j]%=10; 60 } 61 while(ans[len+1]){ 62 len++; 63 ans[len+1]+=ans[len]/10; 64 ans[len]%=10; 65 } 66 pri[i]--; 67 } 68 } 69 for(int i=1;i+2+sum<=N;i++){ 70 for(int j=1;j<=len;j++) ans[j]*=q; 71 for(int j=1;j<=len;j++){ 72 ans[j+1]+=ans[j]/10; 73 ans[j]%=10; 74 } 75 while(ans[len+1]){ 76 len++; 77 ans[len+1]+=ans[len]/10; 78 ans[len]%=10; 79 } 80 } 81 for(int i=len;i>=1;i--) printf("%d",ans[i]); 82 return 0; 83 }
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1005
一个prufer序列可以唯一确定一棵生成树。而prufer序列可以确定节点的度数,反过来,通过度数就可以确定prufer序列的方案数。
具体怎么做贴个黄学长的题解接跑吧……
题解:http://hzwer.com/3272.html