zoukankan      html  css  js  c++  java
  • 【BZOJ1005】[HNOI2008]明明的烦恼

    【BZOJ1005】[HNOI2008]明明的烦恼

    题面

    bzoj

    洛谷

    题解

    前置芝士:

    (prufer)序列

    戳这里

    关于此题

    设有度数限制的点的个数是(cnt),度数为(d[i]),令(sum=sum_{i=1}^{cnt}(d[i]-1))

    不同排列的个数为

    [C_{n-2}^{sum} imesfrac{sum!}{prod_{i=1}^{cnt}(d[i]-1)!} ]

    还剩下(n-2-sum)个位置放(n-cnt)个点,

    经过化简,最后的答案为

    [Ans=(n-cnt)^{n-2-sum} imesfrac{(n-2)!}{(n-2-sum)! imesprod_{i=1}^{cnt}(d[i]-1)!} ]

    然后要写高精qaq。

    (tips:)通过分解质因数避免高精除法。

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm> 
    using namespace std; 
    inline int gi() { 
        register int data = 0, w = 1; 
        register char ch = 0; 
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar(); 
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
        return w * data; 
    }
    const int BASE = 10000; 
    struct Wint { 
    	int num[2005], size; 
    	Wint() { memset(num, 0, sizeof(num)); size = 0; } 
    	void turn(int v) { size = 0; while (v) num[++size] = v % BASE, v /= BASE; } 
    	void write() { printf("%d", num[size]); for (int i = size - 1; i; i--) printf("%04d", num[i]); } 
    } ; 
    Wint operator * (const Wint &a, const int &b) { 
    	Wint c; 
    	for (int i = 1; i <= a.size; i++) c.num[i] = a.num[i] * b; 
    	for (int i = 1; i <= a.size; i++) c.num[i + 1] += c.num[i] / BASE, c.num[i] %= BASE; 
    	int tmp = a.size; 
    	while (c.num[tmp + 1]) ++tmp, c.num[tmp + 1] += c.num[tmp] / BASE, c.num[tmp] %= BASE; 
    	c.size = tmp;
    	return c; 
    } 
    const int MAX_N = 1e4 + 5; 
    int N, a[MAX_N], cnt, sum; 
    int p[MAX_N], p1[MAX_N], p2[MAX_N]; 
    void divisor(int *num, int x) { 
    	for (int i = 2; i * i <= x; i++)
    		while (x % i == 0) ++num[i], x /= i; 
    	if (x != 1) ++num[x]; 
    } 
    int main () {
    #ifndef ONLINE_JUDGE 
        freopen("cpp.in", "r", stdin); 
    #endif 
    	N = gi(); 
    	for (int i = 1; i <= N; i++) {
    		a[i] = gi(); if (a[i] == -1) continue; 
    		++cnt, sum += a[i] - 1; 
    	} 
    	if (sum > N - 2) return puts("0") & 0; 
    	for (int i = 1; i <= N - 2; i++) divisor(p1, i); 
    	for (int i = 1; i <= N - 2 - sum; i++) divisor(p2, i); 
    	for (int i = 1; i <= N; i++) {
    		if (a[i] == -1) continue; 
    		for (int j = 1; j < a[i]; j++) divisor(p2, j); 
    	} 
    	for (int i = 1; i <= N - 2 - sum; i++) divisor(p1, N - cnt); 
    	for (int i = 1; i <= N; i++) p[i] = p1[i] - p2[i]; 
    	Wint ans; 
    	ans.turn(1); 
    	for (int i = 1; i <= N; i++)
    		for (int j = 1; j <= p[i]; j++) ans = ans * i; 
    	ans.write();
    	putchar('
    '); 
    	return 0; 
    } 
    
  • 相关阅读:
    Delphi 枚举所有进程
    从零开始学JAVA(07)-使用SpringMVC4写helloworld
    Delphi下OpenGL2d绘图(06)-画图(多窗口、多视图、多个DC)
    Delphi下OpenGL2d绘图(05)-画图片Bmp
    Delphi下OpenGL2d绘图(04)-画四边形
    Windows下重置MySQL密码【MYSQL】
    HTML5 WEB Storage
    相关转载
    基本的查询流【MSSQL】
    查询编辑器便捷特性【MSSQL】
  • 原文地址:https://www.cnblogs.com/heyujun/p/10553365.html
Copyright © 2011-2022 走看看