BZOJ-1005 明明的烦恼
Prufer编码练习题,这个编码是跟树的生成计数有关系的。
推荐这篇博文:http://www.cnblogs.com/zhj5chengfeng/archive/2013/08/23/3278557.html 介绍地挺全面+生动形象
会了Prufer之后这道题还要用上组合数学来高精度计算。
#include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <fstream> #include <iostream> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define N 12345 #define MAX 1<<30 #define Q 1000000 using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (ch<'0' || ch>'9') { if (ch=='-') f=-1; ch=getchar(); } while (ch>='0' && ch<='9') { x=x*10+ch-'0' ; ch=getchar(); } return x*f; } int n, d[N], k, s, m[N], l; void Mult(int x) { rep(i, 1, l) m[i]*=x; rep(i, 1, l) m[i+1]+=m[i]/Q, m[i]%=Q; while (m[l+1]) l++, m[l+1]+=m[l]/Q, m[l]%=Q; } void Div(int x) { int a=0; down(i, l, 1) a=a*Q+m[i], m[i]=a/x, a%=x; while (m[l]==0 && l>1) l--; } int main() { n=read(); rep(i, 1, n) d[i]=read(); rep(i, 1, n) if (d[i]!=-1) k++, s+=d[i]-1; if (s>n-2) printf("0"); else { m[l=1] = 1; rep(i, 1, n-2) Mult(i); rep(i, 1, n-2-s) Div(i); rep(i, 1, n-2-s) Mult(n-k); rep(i, 1, n) if (d[i]!=-1) rep(j, 1, d[i]-1) Div(j); printf("%d", m[l]); down(i, l-1, 1) if (m[i]>=100000) printf("%d", m[i]); else if (m[i]>=10000) printf("0%d", m[i]); else if (m[i]>=1000) printf("00%d", m[i]); else if (m[i]>=100) printf("000%d", m[i]); else if (m[i]>=10) printf("0000%d", m[i]); else printf("00000%d", m[i]); } return 0; }