【BZOJ 1005】[HNOI2008]明明的烦恼
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
数学相关
我觉得我是做不出来了,只能学一下关于暴力分解的各种咯
1 #include<cstdio> 2 #define mod 100000 3 #include<cmath> 4 using namespace std; 5 int num[1001],ans[1001],pri[1001],d[1010]; 6 int cnt,n,l,m,tot; 7 bool jud(int x){ 8 for(int i=2;i<=sqrt(x);i++) 9 if(x%i==0)return 0; 10 return 1; 11 } 12 13 void getpri(){ 14 for(int i=2;i<=1000;i++) 15 if(jud(i))pri[++cnt]=i; 16 } 17 18 void solve(int a,int f){ 19 for(int i=2;i<=a;i++){ 20 int x=i; 21 for(int j=1;j<=cnt;j++){ 22 if(x==0) break; 23 while(x%pri[j]==0){ 24 num[j]+=f;x/=pri[j]; 25 } 26 } 27 } 28 } 29 30 void mult(int x){ 31 for(int i=1;i<=l;i++) ans[i]*=x; 32 for(int i=1;i<=l;i++) ans[i+1]+=ans[i]/mod,ans[i]%=mod; 33 while(ans[l+1]>0){ 34 l++;ans[l+1]=ans[l]/mod;ans[l]%=mod; 35 } 36 } 37 void print() 38 { 39 for(int i=l;i>0;i--) 40 if(i==l)printf("%d",ans[i]); 41 else printf("%05d",ans[i]); 42 } 43 int main(){ 44 getpri(); 45 int x;ans[1]=1;l=1; 46 scanf("%d",&n); 47 if(n==1){ 48 scanf("%d",&x); 49 if(!x) {printf("1");return 0;} 50 else {printf("0");return 0;} 51 } 52 for(int i=1;i<=n;i++){ 53 scanf("%d",&d[i]); 54 if(d[i]==0) {printf("0");return 0;} 55 if(d[i]==-1) m++; 56 else {d[i]--;tot+=d[i];} 57 } 58 if(tot>n-2){printf("0");return 0;} 59 solve(n-2,1);solve(n-2-tot,-1); 60 for(int i=1;i<=n;i++) if(d[i]) solve(d[i],-1); 61 for(int i=1;i<=n-2-tot;i++) mult(m); 62 for(int i=1;i<=cnt;i++) while(num[i]--) mult(pri[i]); 63 print(); 64 }