博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ.1005.[HNOI2008]明明的烦恼(Prufer 高精 排列组合)
阅读量:5141 次
发布时间:2019-06-13

本文共 1045 字,大约阅读时间需要 3 分钟。

若点数确定那么ans = (n-2)!/[(d1-1)!(d2-1)!...(dn-1)!]

现在把那些不确定的点一起考虑(假设有m个),它们在Prufer序列中总出现数就是left=n-2-(d1-1)-(d2-1)-...-(dn-1)
这left个数本身又有m^{left}种
所以 ans = (n-2)!/[(d1-1)!(d2-1)!...(dn-1)!left!]*m^{left}
显然需要高精度。为避免高精除需要对每个阶乘分解质因数(这个组合数算出来一定是整数,所以分解质因数和分子减掉分母的次数即可)
n!中含质因子p个数公式: f(n)=f(n/p)+n/p
注意下无解的两种情况
要乘的数很小 就容易了

//1228kb 28ms#include 
const int N=1005,Base=10000;int n,dgr[N],up[N],down[N],cnt,P[N],ans[100005];bool Not_P[N+3];void Init(){ Not_P[1]=1; for(int i=2; i
1) tot+=dgr[i]-1, Divide(dgr[i]-1,down); else if(dgr[i]<0) ++m; else if(!dgr[i]) tot=N; } if(tot>n-2 || (tot==n-2&&!m)) {putchar('0'); return 0;} int left=n-2-tot; Divide(n-2,up), Divide(left,down); for(int i=1; i<=cnt; ++i) up[i]-=down[i];// for(int i=1; i<=cnt; ++i) printf("%d^%d\n",P[i],up[i]); ans[ans[0]=1]=1; for(int i=1; i<=cnt; ++i) while(up[i]--) Mult(ans,P[i]); for(int i=1; i<=left; ++i) Mult(ans,m); Print(ans); return 0;}

转载于:https://www.cnblogs.com/SovietPower/p/8483885.html

你可能感兴趣的文章