BZOJ 1005 [HNOI2008]明明的烦恼
2017-02-01 23:36
323 查看
prufer编码+高精度
推荐阅读:Prüfer编码与Cayley公式
还记得自己很久以前也想过有没有某种序列能和树一一对应的,原来是有的。
显然一个性质:度数为m的节点的序号在prufer编码中出现的次数为m-1。
所以把带限制的度数用组合数暴力算一下,没限制也算一下即可。注意这题答案很大,要用高精度。把代码里乘法除法全都改成质因数加减的形式就行了。
想+写没花多久,主要死在高精度上orz。数组开太大会T,开小了又WA,开成longlong又T。。。优化了一下才过
推荐阅读:Prüfer编码与Cayley公式
还记得自己很久以前也想过有没有某种序列能和树一一对应的,原来是有的。
显然一个性质:度数为m的节点的序号在prufer编码中出现的次数为m-1。
所以把带限制的度数用组合数暴力算一下,没限制也算一下即可。注意这题答案很大,要用高精度。把代码里乘法除法全都改成质因数加减的形式就行了。
想+写没花多久,主要死在高精度上orz。数组开太大会T,开小了又WA,开成longlong又T。。。优化了一下才过
#include<cstdio> #include<cstring> #include<algorithm> #define N 1005 #define BASE 1000000 using namespace std; namespace runzhe2000 { int deg , prime , notprime , pcnt, cnt ; struct bigint { long long num[555]; int len; bigint(int x = 0) { memset(num,0,sizeof(num)); num[0] = x; len = 1; for(; num[len-1] >= BASE; ) { num[len] = num[len-1] / BASE; num[len-1] %= BASE; len++; } } bigint operator * (bigint that) { bigint r; for(int i = 0; i < len; i++) for(int j = 0; j < that.len; j++) r.num[i+j] += num[i] * that.num[j]; r.len = len + that.len - 1; for(int i = 0; i < r.len; i++) { r.num[i+1] += r.num[i] / BASE; r.num[i] %= BASE; } if(r.num[r.len])r.len++; return r; } void print() { printf("%lld",num[--len]); for(len--; ~len; len--) printf("%06lld",num[len]); puts(""); } }; bigint fpow(bigint a, int b) { bigint r = 1; for(; b; b>>=1) { if(b&1) r=r*a; a=a*a; } return r; } void make(int a, int v) { if(!v) return; for(int i = 1; i <= pcnt; i++) for(; a % prime[i] == 0; a /= prime[i]) cnt[i] += v; } void makefac(int a, int v) { for(int i = 1; i <= pcnt; i++) { int tmp = a; for(; tmp >= prime[i]; ) { cnt[i] += v * tmp / prime[i]; tmp /= prime[i]; } } } void init_prime(int n) { for(int i = 2; i <= n; i++) { if(!notprime[i]) prime[++pcnt] = i; for(int j = 1; j <= pcnt && prime[j] * i <= n; j++) { notprime[prime[j] * i] = 1; if(i % prime[j] == 0) break; } } } void main() { int n, last, free = 0; scanf("%d",&n); init_prime(n); last = n - 2; for(int i = 1; i <= n; i++) { scanf("%d",°[i]); if(deg[i] == -1) free++; else if(!deg[i] && n != 1){puts("0"); return;} } for(int j = 1; j <= n; j++) { if(deg[j] != -1) { int tmp = deg[j] - 1; if(last < tmp) {last = -1; break;} makefac(last,1); makefac(tmp,-1); makefac(last-tmp,-1); last -= tmp; } } if(last < 0) puts("0"); else { bigint now = 1; make(free,last); for(int i = 1; i <= pcnt; i++) now = now * fpow(prime[i], cnt[i]); now.print(); } } } int main() { runzhe2000::main(); }
相关文章推荐
- Prufer编码 & [bzoj 1005] [HNOI2008]明明的烦恼:Prufer编码,组合数学,高精度
- Bzoj1005 [HNOI2008]明明的烦恼
- [prufer序列]BZOJ1005: [HNOI2008]明明的烦恼
- [bzoj1005][HNOI2008]明明的烦恼
- 【bzoj 1005】 明明的烦恼 【HNOI2008】
- 【BZOJ 1005】[HNOI2008]明明的烦恼 【Prufer序列】
- 【prufer编码+组合数学】BZOJ1005 [HNOI2008]明明的烦恼
- bzoj1005 [HNOI2008]明明的烦恼 prufer+组合数学
- [BZOJ1005][HNOI2008]明明的烦恼&&[BZOJ1211][HNOI2004]树的计数【prufer序列】
- BZOJ1005 [HNOI2008]明明的烦恼
- BZOJ 1005 [HNOI2008]明明的烦恼 purfer序列,排列组合
- BZOJ1005: [HNOI2008]明明的烦恼
- BZOJ_1005_ [HNOI2008]_明明的烦恼_(组合数学+purfer_sequence+高精度+分解因数+快速幂)
- bzoj 1005: [HNOI2008]明明的烦恼 组合数学 + purfer序列
- bzoj 1005: [HNOI2008]明明的烦恼
- 【bzoj1005】 HNOI2008—明明的烦恼
- 【bzoj1005】[HNOI2008]明明的烦恼
- BZOJ 1005: [HNOI2008]明明的烦恼
- bzoj 1005: [HNOI2008]明明的烦恼
- BZOJ.1005.[HNOI2008]明明的烦恼(Prufer 高精 排列组合)